DEADSOFTWARE

log messages now written to console too
[d2df-sdl.git] / src / game / g_console.pas
1 {$MODE DELPHI}
2 unit g_console;
4 interface
6 procedure g_Console_Init();
7 procedure g_Console_Update();
8 procedure g_Console_Draw();
9 procedure g_Console_Switch();
10 procedure g_Console_Char(C: Char);
11 procedure g_Console_Control(K: Word);
12 procedure g_Console_Process(L: String; Quiet: Boolean = False);
13 procedure g_Console_Add(L: String; Show: Boolean = False);
14 procedure g_Console_Clear();
15 function g_Console_CommandBlacklisted(C: String): Boolean;
17 procedure g_Console_Chat_Switch(Team: Boolean = False);
19 var
20 gConsoleShow: Boolean; // True - êîíñîëü îòêðûòà èëè îòêðûâàåòñÿ
21 gChatShow: Boolean;
22 gChatTeam: Boolean = False;
23 gAllowConsoleMessages: Boolean = True;
24 gChatEnter: Boolean = True;
25 gJustChatted: Boolean = False; // ÷òîáû àäìèí â èíòåðå ÷àòÿñü íå ïðîìàòûâàë ñòàòèñòèêó
27 implementation
29 uses
30 g_textures, g_main, e_graphics, e_input, g_game,
31 SysUtils, g_basic, g_options, wadreader, Math,
32 g_menu, g_language, g_net, g_netmsg, e_log, conbuf;
34 type
35 TCmdProc = procedure (P: SArray);
37 TCommand = record
38 Cmd: String;
39 Proc: TCmdProc;
40 end;
42 TAlias = record
43 Name: String;
44 Commands: SArray;
45 end;
47 const
48 Step = 32;
49 Alpha = 25;
50 MsgTime = 144;
51 MaxScriptRecursion = 16;
53 DEBUG_STRING = 'DEBUG MODE';
55 var
56 ID: DWORD;
57 RecursionDepth: Word = 0;
58 RecursionLimitHit: Boolean = False;
59 Cons_Y: SmallInt;
60 Cons_Shown: Boolean; // Ðèñîâàòü ëè êîíñîëü?
61 Line: String;
62 CPos: Word;
63 //ConsoleHistory: SArray;
64 CommandHistory: SArray;
65 Whitelist: SArray;
66 Commands: Array of TCommand;
67 Aliases: Array of TAlias;
68 CmdIndex: Word;
69 conSkipLines: Integer = 0;
70 MsgArray: Array [0..4] of record
71 Msg: String;
72 Time: Word;
73 end;
75 function GetStrACmd(var Str: String): String;
76 var
77 a: Integer;
78 begin
79 Result := '';
80 for a := 1 to Length(Str) do
81 if (a = Length(Str)) or (Str[a+1] = ';') then
82 begin
83 Result := Copy(Str, 1, a);
84 Delete(Str, 1, a+1);
85 Str := Trim(Str);
86 Exit;
87 end;
88 end;
90 function ParseAlias(Str: String): SArray;
91 begin
92 Result := nil;
94 Str := Trim(Str);
96 if Str = '' then
97 Exit;
99 while Str <> '' do
100 begin
101 SetLength(Result, Length(Result)+1);
102 Result[High(Result)] := GetStrACmd(Str);
103 end;
104 end;
106 procedure ConsoleCommands(P: SArray);
107 var
108 Cmd, s: String;
109 a, b: Integer;
110 F: TextFile;
111 begin
112 Cmd := LowerCase(P[0]);
113 s := '';
115 if Cmd = 'clear' then
116 begin
117 //ConsoleHistory := nil;
118 cbufClear();
119 conSkipLines := 0;
121 for a := 0 to High(MsgArray) do
122 with MsgArray[a] do
123 begin
124 Msg := '';
125 Time := 0;
126 end;
127 end;
129 if Cmd = 'clearhistory' then
130 CommandHistory := nil;
132 if Cmd = 'showhistory' then
133 if CommandHistory <> nil then
134 begin
135 g_Console_Add('');
136 for a := 0 to High(CommandHistory) do
137 g_Console_Add(' '+CommandHistory[a]);
138 end;
140 if Cmd = 'commands' then
141 begin
142 g_Console_Add('');
143 g_Console_Add('Commands list:');
144 for a := High(Commands) downto 0 do
145 g_Console_Add(' '+Commands[a].Cmd);
146 end;
148 if Cmd = 'time' then
149 g_Console_Add(TimeToStr(Now), True);
151 if Cmd = 'date' then
152 g_Console_Add(DateToStr(Now), True);
154 if Cmd = 'echo' then
155 if Length(P) > 1 then
156 begin
157 if P[1] = 'ololo' then
158 gCheats := True
159 else
160 begin
161 s := '';
162 for a := 1 to High(P) do
163 s := s + P[a] + ' ';
164 g_Console_Add(b_Text_Format(s), True);
165 end;
166 end
167 else
168 g_Console_Add('');
170 if Cmd = 'dump' then
171 begin
172 (*
173 if ConsoleHistory <> nil then
174 begin
175 if Length(P) > 1 then
176 s := P[1]
177 else
178 s := GameDir+'/console.txt';
180 {$I-}
181 AssignFile(F, s);
182 Rewrite(F);
183 if IOResult <> 0 then
184 begin
185 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [s]));
186 CloseFile(F);
187 Exit;
188 end;
190 for a := 0 to High(ConsoleHistory) do
191 WriteLn(F, ConsoleHistory[a]);
193 CloseFile(F);
194 g_Console_Add(Format(_lc[I_CONSOLE_DUMPED], [s]));
195 {$I+}
196 end;
197 *)
198 end;
200 if Cmd = 'exec' then
201 begin
202 // exec <filename>
203 if Length(P) > 1 then
204 begin
205 s := GameDir+'/'+P[1];
207 {$I-}
208 AssignFile(F, s);
209 Reset(F);
210 if IOResult <> 0 then
211 begin
212 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_READ], [s]));
213 CloseFile(F);
214 Exit;
215 end;
216 g_Console_Add(Format(_lc[I_CONSOLE_EXEC], [s]));
218 while not EOF(F) do
219 begin
220 ReadLn(F, s);
221 if IOResult <> 0 then
222 begin
223 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_READ], [s]));
224 CloseFile(F);
225 Exit;
226 end;
227 if Pos('#', s) <> 1 then // script comment
228 begin
229 // prevents endless loops
230 Inc(RecursionDepth);
231 RecursionLimitHit := (RecursionDepth > MaxScriptRecursion) or RecursionLimitHit;
232 if not RecursionLimitHit then
233 g_Console_Process(s, True);
234 Dec(RecursionDepth);
235 end;
236 end;
237 if (RecursionDepth = 0) and RecursionLimitHit then
238 begin
239 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_CALL], [s]));
240 RecursionLimitHit := False;
241 end;
243 CloseFile(F);
244 {$I+}
245 end
246 else
247 g_Console_Add('exec <script file>');
248 end;
250 if Cmd = 'alias' then
251 begin
252 // alias [alias_name] [commands]
253 if Length(P) > 1 then
254 begin
255 for a := 0 to High(Aliases) do
256 if Aliases[a].Name = P[1] then
257 begin
258 if Length(P) > 2 then
259 Aliases[a].Commands := ParseAlias(P[2])
260 else
261 for b := 0 to High(Aliases[a].Commands) do
262 g_Console_Add(Aliases[a].Commands[b]);
263 Exit;
264 end;
265 SetLength(Aliases, Length(Aliases)+1);
266 a := High(Aliases);
267 Aliases[a].Name := P[1];
268 if Length(P) > 2 then
269 Aliases[a].Commands := ParseAlias(P[2])
270 else
271 for b := 0 to High(Aliases[a].Commands) do
272 g_Console_Add(Aliases[a].Commands[b]);
273 end else
274 for a := 0 to High(Aliases) do
275 if Aliases[a].Commands <> nil then
276 g_Console_Add(Aliases[a].Name);
277 end;
279 if Cmd = 'call' then
280 begin
281 // call <alias_name>
282 if Length(P) > 1 then
283 begin
284 if Aliases = nil then
285 Exit;
286 for a := 0 to High(Aliases) do
287 if Aliases[a].Name = P[1] then
288 begin
289 if Aliases[a].Commands <> nil then
290 begin
291 // with this system proper endless loop detection seems either impossible
292 // or very dirty to implement, so let's have this instead
293 // prevents endless loops
294 for b := 0 to High(Aliases[a].Commands) do
295 begin
296 Inc(RecursionDepth);
297 RecursionLimitHit := (RecursionDepth > MaxScriptRecursion) or RecursionLimitHit;
298 if not RecursionLimitHit then
299 g_Console_Process(Aliases[a].Commands[b], True);
300 Dec(RecursionDepth);
301 end;
302 if (RecursionDepth = 0) and RecursionLimitHit then
303 begin
304 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_CALL], [s]));
305 RecursionLimitHit := False;
306 end;
307 end;
308 Exit;
309 end;
310 end
311 else
312 g_Console_Add('call <alias name>');
313 end;
314 end;
316 procedure WhitelistCommand(Cmd: string);
317 var
318 a: Integer;
319 begin
320 SetLength(Whitelist, Length(Whitelist)+1);
321 a := High(Whitelist);
322 Whitelist[a] := Cmd;
323 end;
325 procedure AddCommand(Cmd: String; Proc: TCmdProc);
326 var
327 a: Integer;
328 begin
329 SetLength(Commands, Length(Commands)+1);
330 a := High(Commands);
331 Commands[a].Cmd := Cmd;
332 Commands[a].Proc := Proc;
333 end;
335 procedure g_Console_Init();
336 var
337 a: Integer;
338 begin
339 g_Texture_CreateWAD(ID, GameWAD+':TEXTURES\CONSOLE');
340 Cons_Y := -(gScreenHeight div 2);
341 gConsoleShow := False;
342 gChatShow := False;
343 Cons_Shown := False;
344 CPos := 1;
346 for a := 0 to High(MsgArray) do
347 with MsgArray[a] do
348 begin
349 Msg := '';
350 Time := 0;
351 end;
353 AddCommand('clear', ConsoleCommands);
354 AddCommand('clearhistory', ConsoleCommands);
355 AddCommand('showhistory', ConsoleCommands);
356 AddCommand('commands', ConsoleCommands);
357 AddCommand('time', ConsoleCommands);
358 AddCommand('date', ConsoleCommands);
359 AddCommand('echo', ConsoleCommands);
360 AddCommand('dump', ConsoleCommands);
361 AddCommand('exec', ConsoleCommands);
362 AddCommand('alias', ConsoleCommands);
363 AddCommand('call', ConsoleCommands);
365 AddCommand('d_window', DebugCommands);
366 AddCommand('d_sounds', DebugCommands);
367 AddCommand('d_frames', DebugCommands);
368 AddCommand('d_winmsg', DebugCommands);
369 AddCommand('d_monoff', DebugCommands);
370 AddCommand('d_botoff', DebugCommands);
371 AddCommand('d_monster', DebugCommands);
372 AddCommand('d_health', DebugCommands);
373 AddCommand('d_player', DebugCommands);
374 AddCommand('d_joy', DebugCommands);
376 AddCommand('p1_name', GameCVars);
377 AddCommand('p2_name', GameCVars);
378 AddCommand('p1_color', GameCVars);
379 AddCommand('p2_color', GameCVars);
380 AddCommand('r_showfps', GameCVars);
381 AddCommand('r_showtime', GameCVars);
382 AddCommand('r_showscore', GameCVars);
383 AddCommand('r_showlives', GameCVars);
384 AddCommand('r_showstat', GameCVars);
385 AddCommand('r_showkillmsg', GameCVars);
386 AddCommand('r_showspect', GameCVars);
387 AddCommand('r_showping', GameCVars);
388 AddCommand('g_gamemode', GameCVars);
389 AddCommand('g_friendlyfire', GameCVars);
390 AddCommand('g_weaponstay', GameCVars);
391 AddCommand('g_allow_exit', GameCVars);
392 AddCommand('g_allow_monsters', GameCVars);
393 AddCommand('g_bot_vsmonsters', GameCVars);
394 AddCommand('g_bot_vsplayers', GameCVars);
395 AddCommand('g_scorelimit', GameCVars);
396 AddCommand('g_timelimit', GameCVars);
397 AddCommand('g_maxlives', GameCVars);
398 AddCommand('g_warmuptime', GameCVars);
399 AddCommand('net_interp', GameCVars);
400 AddCommand('net_forceplayerupdate', GameCVars);
401 AddCommand('net_predictself', GameCVars);
402 AddCommand('sv_name', GameCVars);
403 AddCommand('sv_passwd', GameCVars);
404 AddCommand('sv_maxplrs', GameCVars);
405 AddCommand('sv_public', GameCVars);
406 AddCommand('sv_intertime', GameCVars);
408 AddCommand('quit', GameCommands);
409 AddCommand('exit', GameCommands);
410 AddCommand('pause', GameCommands);
411 AddCommand('endgame', GameCommands);
412 AddCommand('restart', GameCommands);
413 AddCommand('addbot', GameCommands);
414 AddCommand('bot_add', GameCommands);
415 AddCommand('bot_addlist', GameCommands);
416 AddCommand('bot_addred', GameCommands);
417 AddCommand('bot_addblue', GameCommands);
418 AddCommand('bot_removeall', GameCommands);
419 AddCommand('chat', GameCommands);
420 AddCommand('teamchat', GameCommands);
421 AddCommand('game', GameCommands);
422 AddCommand('host', GameCommands);
423 AddCommand('map', GameCommands);
424 AddCommand('nextmap', GameCommands);
425 AddCommand('endmap', GameCommands);
426 AddCommand('goodbye', GameCommands);
427 AddCommand('suicide', GameCommands);
428 AddCommand('spectate', GameCommands);
429 AddCommand('ready', GameCommands);
430 AddCommand('kick', GameCommands);
431 AddCommand('kick_id', GameCommands);
432 AddCommand('ban', GameCommands);
433 AddCommand('permban', GameCommands);
434 AddCommand('ban_id', GameCommands);
435 AddCommand('permban_id', GameCommands);
436 AddCommand('unban', GameCommands);
437 AddCommand('connect', GameCommands);
438 AddCommand('disconnect', GameCommands);
439 AddCommand('reconnect', GameCommands);
440 AddCommand('say', GameCommands);
441 AddCommand('tell', GameCommands);
442 AddCommand('overtime', GameCommands);
443 AddCommand('rcon_password', GameCommands);
444 AddCommand('rcon', GameCommands);
445 AddCommand('callvote', GameCommands);
446 AddCommand('vote', GameCommands);
447 AddCommand('clientlist', GameCommands);
448 AddCommand('event', GameCommands);
450 AddCommand('god', GameCheats);
451 AddCommand('notarget', GameCheats);
452 AddCommand('give', GameCheats); // "exit" too ;-)
453 AddCommand('open', GameCheats);
454 AddCommand('fly', GameCheats);
455 AddCommand('noclip', GameCheats);
456 AddCommand('speedy', GameCheats);
457 AddCommand('jumpy', GameCheats);
458 AddCommand('noreload', GameCheats);
459 AddCommand('aimline', GameCheats);
460 AddCommand('automap', GameCheats);
462 WhitelistCommand('say');
463 WhitelistCommand('tell');
464 WhitelistCommand('overtime');
465 WhitelistCommand('ready');
466 WhitelistCommand('map');
467 WhitelistCommand('nextmap');
468 WhitelistCommand('endmap');
469 WhitelistCommand('restart');
470 WhitelistCommand('kick');
471 WhitelistCommand('ban');
473 WhitelistCommand('addbot');
474 WhitelistCommand('bot_add');
475 WhitelistCommand('bot_addred');
476 WhitelistCommand('bot_addblue');
477 WhitelistCommand('bot_removeall');
479 WhitelistCommand('g_gamemode');
480 WhitelistCommand('g_friendlyfire');
481 WhitelistCommand('g_weaponstay');
482 WhitelistCommand('g_allow_exit');
483 WhitelistCommand('g_allow_monsters');
484 WhitelistCommand('g_scorelimit');
485 WhitelistCommand('g_timelimit');
487 g_Console_Add(Format(_lc[I_CONSOLE_WELCOME], [GAME_VERSION]));
488 g_Console_Add('');
489 end;
491 procedure g_Console_Update();
492 var
493 a, b: Integer;
494 begin
495 if Cons_Shown then
496 begin
497 // Â ïðîöåññå îòêðûòèÿ:
498 if gConsoleShow and (Cons_Y < 0) then
499 begin
500 Cons_Y := Cons_Y+Step;
501 end;
503 // Â ïðîöåññå çàêðûòèÿ:
504 if (not gConsoleShow) and
505 (Cons_Y > -(gScreenHeight div 2)) then
506 Cons_Y := Cons_Y-Step;
508 // Îêîí÷àòåëüíî îòêðûëàñü:
509 if Cons_Y > 0 then
510 Cons_Y := 0;
512 // Îêîí÷àòåëüíî çàêðûëàñü:
513 if Cons_Y <= (-(gScreenHeight div 2)) then
514 begin
515 Cons_Y := -(gScreenHeight div 2);
516 Cons_Shown := False;
517 end;
518 end;
520 a := 0;
521 while a <= High(MsgArray) do
522 begin
523 if MsgArray[a].Time > 0 then
524 begin
525 if MsgArray[a].Time = 1 then
526 begin
527 if a < High(MsgArray) then
528 begin
529 for b := a to High(MsgArray)-1 do
530 MsgArray[b] := MsgArray[b+1];
532 MsgArray[High(MsgArray)].Time := 0;
534 a := a - 1;
535 end;
536 end
537 else
538 Dec(MsgArray[a].Time);
539 end;
541 a := a + 1;
542 end;
543 end;
546 procedure drawConsoleText ();
547 var
548 CWidth, CHeight: Byte;
549 ty: Integer;
550 sp, ep: LongWord;
551 skip: Integer;
553 procedure putLine (sp, ep: LongWord);
554 var
555 p: LongWord;
556 wdt, cw: Integer;
557 begin
558 p := sp;
559 wdt := 0;
560 while p <> ep do
561 begin
562 cw := e_TextureFontCharWidth(cbufAt(p), gStdFont);
563 if wdt+cw > gScreenWidth-8 then break;
564 //e_TextureFontPrintChar(X, Y: Integer; Ch: Char; FontID: DWORD; Shadow: Boolean = False);
565 Inc(wdt, cw);
566 cbufNext(p);
567 end;
568 if p <> ep then putLine(p, ep); // do rest of the line first
569 // now print our part
570 if skip = 0 then
571 begin
572 ep := p;
573 p := sp;
574 wdt := 2;
575 while p <> ep do
576 begin
577 cw := e_TextureFontCharWidth(cbufAt(p), gStdFont);
578 e_TextureFontPrintCharEx(wdt, ty, cbufAt(p), gStdFont);
579 Inc(wdt, cw);
580 cbufNext(p);
581 end;
582 Dec(ty, CHeight);
583 end
584 else
585 begin
586 Dec(skip);
587 end;
588 end;
590 begin
591 e_TextureFontGetSize(gStdFont, CWidth, CHeight);
592 ty := (gScreenHeight div 2)-4-2*CHeight-Abs(Cons_Y);
593 skip := conSkipLines;
594 cbufLastLine(sp, ep);
595 repeat
596 putLine(sp, ep);
597 if ty+CHeight <= 0 then break;
598 until not cbufLineUp(sp, ep);
599 end;
601 procedure g_Console_Draw();
602 var
603 CWidth, CHeight: Byte;
604 mfW, mfH: Word;
605 a, b: Integer;
606 begin
607 e_TextureFontGetSize(gStdFont, CWidth, CHeight);
609 for a := 0 to High(MsgArray) do
610 if MsgArray[a].Time > 0 then
611 e_TextureFontPrintFmt(0, CHeight*a, MsgArray[a].Msg,
612 gStdFont, True);
614 if not Cons_Shown then
615 begin
616 if gChatShow then
617 begin
618 if gChatTeam then
619 begin
620 e_TextureFontPrintEx(0, gScreenHeight - CHeight - 1, 'say team> ' + Line,
621 gStdFont, 255, 255, 255, 1, True);
622 e_TextureFontPrintEx((CPos + 9)*CWidth, gScreenHeight - CHeight - 1, '_',
623 gStdFont, 255, 255, 255, 1, True);
624 end
625 else
626 begin
627 e_TextureFontPrintEx(0, gScreenHeight - CHeight - 1, 'say> ' + Line,
628 gStdFont, 255, 255, 255, 1, True);
629 e_TextureFontPrintEx((CPos + 4)*CWidth, gScreenHeight - CHeight - 1, '_',
630 gStdFont, 255, 255, 255, 1, True);
631 end;
632 end;
633 Exit;
634 end;
636 if gDebugMode then
637 begin
638 e_CharFont_GetSize(gMenuFont, DEBUG_STRING, mfW, mfH);
639 a := (gScreenWidth - 2*mfW) div 2;
640 b := Cons_Y + ((gScreenHeight div 2) - 2*mfH) div 2;
641 e_CharFont_PrintEx(gMenuFont, a div 2, b div 2, DEBUG_STRING,
642 _RGB(128, 0, 0), 2.0);
643 end;
645 e_DrawSize(ID, 0, Cons_Y, Alpha, False, False, gScreenWidth, gScreenHeight div 2);
646 e_TextureFontPrint(0, Cons_Y+(gScreenHeight div 2)-CHeight-4, '> '+Line, gStdFont);
648 drawConsoleText();
649 (*
650 if ConsoleHistory <> nil then
651 begin
652 b := 0;
653 if CHeight > 0 then
654 if Length(ConsoleHistory) > ((gScreenHeight div 2) div CHeight)-1 then
655 b := Length(ConsoleHistory)-((gScreenHeight div 2) div CHeight)+1;
657 b := Max(b-Offset, 0);
658 d := Max(High(ConsoleHistory)-Offset, 0);
660 c := 2;
661 for a := d downto b do
662 begin
663 e_TextureFontPrintFmt(0, (gScreenHeight div 2)-4-c*CHeight-Abs(Cons_Y), ConsoleHistory[a],
664 gStdFont, True);
665 c := c + 1;
666 end;
667 end;
668 *)
670 e_TextureFontPrint((CPos+1)*CWidth, Cons_Y+(gScreenHeight div 2)-21, '_', gStdFont);
671 end;
673 procedure g_Console_Switch();
674 begin
675 if gChatShow then Exit;
676 gConsoleShow := not gConsoleShow;
677 Cons_Shown := True;
678 end;
680 procedure g_Console_Chat_Switch(Team: Boolean = False);
681 begin
682 if gConsoleShow then Exit;
683 if not g_Game_IsNet then Exit;
684 gChatShow := not gChatShow;
685 gChatTeam := Team;
686 if gChatShow then
687 gChatEnter := False;
688 Line := '';
689 CPos := 1;
690 end;
692 procedure g_Console_Char(C: Char);
693 begin
694 if gChatShow and (not gChatEnter) then
695 Exit;
696 Insert(C, Line, CPos);
697 CPos := CPos + 1;
698 end;
700 procedure Complete();
701 var
702 i: Integer;
703 t: Array of String;
704 begin
705 if Line = '' then
706 Exit;
708 t := nil;
710 for i := 0 to High(Commands) do
711 if LowerCase(Line) = LowerCase(Copy(Commands[i].Cmd, 0, Length(Line))) then
712 begin
713 SetLength(t, Length(t) + 1);
714 t[Length(t)-1] := Commands[i].Cmd;
715 end;
717 if t = nil then
718 Exit;
720 if Length(t) = 1 then
721 begin
722 Line := t[0]+' ';
723 CPos := Length(Line)+1;
724 end
725 else
726 begin
727 g_Console_Add('');
728 for i := 0 to High(t) do
729 g_Console_Add(' '+t[i]);
730 end;
731 end;
733 procedure g_Console_Control(K: Word);
734 begin
735 case K of
736 IK_BACKSPACE:
737 if (Length(Line) > 0) and (CPos > 1) then
738 begin
739 Delete(Line, CPos-1, 1);
740 CPos := CPos-1;
741 end;
742 IK_DELETE:
743 if (Length(Line) > 0) and (CPos <= Length(Line)) then
744 Delete(Line, CPos, 1);
745 IK_LEFT, IK_KPLEFT:
746 if CPos > 1 then
747 CPos := CPos - 1;
748 IK_RIGHT, IK_KPRIGHT:
749 if CPos <= Length(Line) then
750 CPos := CPos + 1;
751 IK_RETURN, IK_KPRETURN:
752 begin
753 if Cons_Shown then
754 g_Console_Process(Line)
755 else
756 if gChatShow then
757 begin
758 if (Length(Line) > 0) and g_Game_IsNet then
759 begin
760 if gChatTeam then
761 begin
762 if g_Game_IsClient then
763 MC_SEND_Chat(b_Text_Format(Line), NET_CHAT_TEAM)
764 else
765 MH_SEND_Chat('[' + gPlayer1Settings.Name + ']: ' + b_Text_Format(Line),
766 NET_CHAT_TEAM, gPlayer1Settings.Team);
767 end
768 else
769 begin
770 if g_Game_IsClient then
771 MC_SEND_Chat(b_Text_Format(Line), NET_CHAT_PLAYER)
772 else
773 MH_SEND_Chat('[' + gPlayer1Settings.Name + ']: ' + b_Text_Format(Line),
774 NET_CHAT_PLAYER);
775 end;
776 end;
778 Line := '';
779 CPos := 1;
780 gChatShow := False;
781 gJustChatted := True;
782 end;
783 end;
784 IK_TAB:
785 if not gChatShow then
786 Complete();
787 IK_DOWN, IK_KPDOWN:
788 if not gChatShow then
789 if (CommandHistory <> nil) and
790 (CmdIndex < Length(CommandHistory)) then
791 begin
792 if CmdIndex < Length(CommandHistory)-1 then
793 CmdIndex := CmdIndex + 1;
794 Line := CommandHistory[CmdIndex];
795 CPos := Length(Line) + 1;
796 end;
797 IK_UP, IK_KPUP:
798 if not gChatShow then
799 if (CommandHistory <> nil) and
800 (CmdIndex <= Length(CommandHistory)) then
801 begin
802 if CmdIndex > 0 then
803 CmdIndex := CmdIndex - 1;
804 Line := CommandHistory[CmdIndex];
805 Cpos := Length(Line) + 1;
806 end;
807 IK_PAGEUP, IK_KPPAGEUP: // PgUp
808 if not gChatShow then Inc(conSkipLines);
809 IK_PAGEDN, IK_KPPAGEDN: // PgDown
810 if not gChatShow and (conSkipLines > 0) then Dec(conSkipLines);
811 IK_HOME, IK_KPHOME:
812 CPos := 1;
813 IK_END, IK_KPEND:
814 CPos := Length(Line) + 1;
815 end;
816 end;
818 function GetStr(var Str: String): String;
819 var
820 a, b: Integer;
821 begin
822 Result := '';
823 if Str[1] = '"' then
824 begin
825 for b := 1 to Length(Str) do
826 if (b = Length(Str)) or (Str[b+1] = '"') then
827 begin
828 Result := Copy(Str, 2, b-1);
829 Delete(Str, 1, b+1);
830 Str := Trim(Str);
831 Exit;
832 end;
833 end;
835 for a := 1 to Length(Str) do
836 if (a = Length(Str)) or (Str[a+1] = ' ') then
837 begin
838 Result := Copy(Str, 1, a);
839 Delete(Str, 1, a+1);
840 Str := Trim(Str);
841 Exit;
842 end;
843 end;
845 function ParseString(Str: String): SArray;
846 begin
847 Result := nil;
849 Str := Trim(Str);
851 if Str = '' then
852 Exit;
854 while Str <> '' do
855 begin
856 SetLength(Result, Length(Result)+1);
857 Result[High(Result)] := GetStr(Str);
858 end;
859 end;
861 procedure g_Console_Add(L: String; Show: Boolean = False);
862 {var
863 a: Integer;}
864 begin
865 // Âûâîä ñòðîê ñ ïåðåíîñàìè ïî î÷åðåäè
867 while Pos(#10, L) > 0 do
868 begin
869 g_Console_Add(Copy(L, 1, Pos(#10, L) - 1), Show);
870 Delete(L, 1, Pos(#10, L));
871 end;
874 //SetLength(ConsoleHistory, Length(ConsoleHistory)+1);
875 //ConsoleHistory[High(ConsoleHistory)] := L;
877 cbufPut(L);
878 if (length(L) = 0) or ((L[length(L)] <> #10) and (L[length(L)] <> #13)) then cbufPut(#10);
880 (*
881 Show := Show and gAllowConsoleMessages;
883 if Show and gShowMessages then
884 begin
885 for a := 0 to High(MsgArray) do
886 with MsgArray[a] do
887 if Time = 0 then
888 begin
889 Msg := L;
890 Time := MsgTime;
891 Exit;
892 end;
894 for a := 0 to High(MsgArray)-1 do
895 MsgArray[a] := MsgArray[a+1];
897 with MsgArray[High(MsgArray)] do
898 begin
899 Msg := L;
900 Time := MsgTime;
901 end;
902 end;
904 {$IFDEF HEADLESS}
905 e_WriteLog('CON: ' + L, MSG_NOTIFY);
906 {$ENDIF}
907 *)
908 end;
910 procedure g_Console_Clear();
911 begin
912 //ConsoleHistory := nil;
913 cbufClear();
914 conSkipLines := 0;
915 end;
917 procedure AddToHistory(L: String);
918 var
919 len: Integer;
920 begin
921 len := Length(CommandHistory);
923 if (len = 0) or
924 (LowerCase(CommandHistory[len-1]) <> LowerCase(L)) then
925 begin
926 SetLength(CommandHistory, len+1);
927 CommandHistory[len] := L;
928 end;
930 CmdIndex := Length(CommandHistory);
931 end;
933 function g_Console_CommandBlacklisted(C: String): Boolean;
934 var
935 Arr: SArray;
936 i: Integer;
937 begin
938 Result := True;
940 Arr := nil;
942 if Trim(C) = '' then
943 Exit;
945 Arr := ParseString(C);
946 if Arr = nil then
947 Exit;
949 for i := 0 to High(Whitelist) do
950 if Whitelist[i] = LowerCase(Arr[0]) then
951 Result := False;
952 end;
954 procedure g_Console_Process(L: String; Quiet: Boolean = False);
955 var
956 Arr: SArray;
957 i: Integer;
958 begin
959 Arr := nil;
961 if Trim(L) = '' then
962 Exit;
964 if L = 'goobers' then
965 begin
966 Line := '';
967 CPos := 1;
968 gCheats := true;
969 g_Console_Add('Your memory serves you well.');
970 exit;
971 end;
973 if not Quiet then
974 begin
975 g_Console_Add('> '+L);
976 Line := '';
977 CPos := 1;
978 end;
980 Arr := ParseString(L);
981 if Arr = nil then
982 Exit;
984 if Commands = nil then
985 Exit;
987 if not Quiet then
988 AddToHistory(L);
990 for i := 0 to High(Commands) do
991 if Commands[i].Cmd = LowerCase(Arr[0]) then
992 if @Commands[i].Proc <> nil then
993 begin
994 Commands[i].Proc(Arr);
995 Exit;
996 end;
998 g_Console_Add(Format(_lc[I_CONSOLE_UNKNOWN], [Arr[0]]));
999 end;
1001 end.