X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fgame%2Fg_console.pas;h=ecc6677e9d30b0b97ecffbc8e9a378d40520b011;hb=935ed9a1e12d78a0c4ef4a9e9f9bf858fd2c2b56;hp=e0f401deeade15964e5c93c103ecebfa6065088c;hpb=98ad2c936a61bb810453f3552d7ed273eeaeaef3;p=d2df-sdl.git diff --git a/src/game/g_console.pas b/src/game/g_console.pas index e0f401d..ecc6677 100644 --- a/src/game/g_console.pas +++ b/src/game/g_console.pas @@ -1,4 +1,4 @@ -(* Copyright (C) DooM 2D:Forever Developers +(* Copyright (C) Doom 2D: Forever Developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,36 @@ unit g_console; interface uses - wadreader; // for SArray + utils; // for SSArray + + const + ACTION_MOVEUP = 1; + ACTION_MOVEDOWN = 2; + ACTION_MOVELEFT = 3; + ACTION_MOVERIGHT = 4; + ACTION_SPEED = 5; + ACTION_SCORES = 6; + ACTION_LOOKDOWN = 7; + ACTION_LOOKUP = 8; + ACTION_ATTACK = 9; + ACTION_ACTIVATE = 10; + ACTION_STRAFE = 11; + ACTION_WEAPNEXT = 12; + ACTION_WEAPPREV = 13; + ACTION_WEAP1 = 14; + ACTION_WEAP2 = 15; + ACTION_WEAP3 = 16; + ACTION_WEAP4 = 17; + ACTION_WEAP5 = 18; + ACTION_WEAP6 = 19; + ACTION_WEAP7 = 20; + ACTION_WEAP8 = 21; + ACTION_WEAP9 = 22; + ACTION_WEAP10 = 23; + ACTION_WEAP11 = 24; + + LAST_ACTION = ACTION_WEAP11; + MAX_ACTION_WEAP = ACTION_WEAP11 - ACTION_WEAP1 + 1; procedure g_Console_Init (); procedure g_Console_Update (); @@ -31,17 +60,24 @@ procedure g_Console_Process (L: AnsiString; quiet: Boolean=false); procedure g_Console_Add (L: AnsiString; show: Boolean=false); procedure g_Console_Clear (); function g_Console_CommandBlacklisted (C: AnsiString): Boolean; +procedure g_Console_ReadConfig (filename: String); + +procedure g_Console_ProcessBind (key: Integer; down: Boolean); procedure conwriteln (const s: AnsiString; show: Boolean=false); procedure conwritefln (const s: AnsiString; args: array of const; show: Boolean=false); // <0: no arg; 0/1: true/false -function conGetBoolArg (p: SArray; idx: Integer): Integer; +function conGetBoolArg (p: SSArray; idx: Integer): Integer; procedure g_Console_Chat_Switch (team: Boolean=false); -procedure conRegVar (const conname: AnsiString; pvar: PBoolean; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false); overload; -procedure conRegVar (const conname: AnsiString; pvar: PSingle; amin, amax: Single; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false); overload; +procedure conRegVar (const conname: AnsiString; pvar: PBoolean; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload; +procedure conRegVar (const conname: AnsiString; pvar: PSingle; amin, amax: Single; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload; +procedure conRegVar (const conname: AnsiString; pvar: PInteger; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload; + +// poor man's floating literal parser; i'm sorry, but `StrToFloat()` sux cocks +function conParseFloat (var res: Single; const s: AnsiString): Boolean; var @@ -51,21 +87,21 @@ var gAllowConsoleMessages: Boolean = true; gChatEnter: Boolean = true; gJustChatted: Boolean = false; // ÷òîáû àäìèí â èíòåðå ÷àòÿñü íå ïðîìàòûâàë ñòàòèñòèêó - + gPlayerAction: Array [0..1, 0..LAST_ACTION] of Boolean; // [player, action] implementation uses g_textures, g_main, e_graphics, e_input, g_game, - SysUtils, g_basic, g_options, Math, - g_menu, g_language, g_net, g_netmsg, e_log, conbuf, utils; + SysUtils, g_basic, g_options, Math, g_touch, + g_menu, g_language, g_net, g_netmsg, e_log, conbuf; type PCommand = ^TCommand; - TCmdProc = procedure (p: SArray); - TCmdProcEx = procedure (me: PCommand; p: SArray); + TCmdProc = procedure (p: SSArray); + TCmdProcEx = procedure (me: PCommand; p: SSArray); TCommand = record cmd: AnsiString; @@ -80,7 +116,7 @@ type TAlias = record name: AnsiString; - commands: SArray; + commands: SSArray; end; @@ -100,9 +136,9 @@ var Cons_Shown: Boolean; // Ðèñîâàòü ëè êîíñîëü? Line: AnsiString; CPos: Word; - //ConsoleHistory: SArray; - CommandHistory: SArray; - Whitelist: SArray; + //ConsoleHistory: SSArray; + CommandHistory: SSArray; + Whitelist: SSArray; commands: Array of TCommand = nil; Aliases: Array of TAlias = nil; CmdIndex: Word; @@ -111,11 +147,54 @@ var Msg: AnsiString; Time: Word; end; + gInputBinds: Array [0..e_MaxInputKeys - 1] of record + cmd: AnsiString + end; + bindDown, bindProcess: Boolean; + + +// poor man's floating literal parser; i'm sorry, but `StrToFloat()` sux cocks +function conParseFloat (var res: Single; const s: AnsiString): Boolean; +var + pos: Integer = 1; + frac: Single = 1; + slen: Integer; +begin + result := false; + res := 0; + slen := Length(s); + while (slen > 0) and (s[slen] <= ' ') do Dec(slen); + while (pos <= slen) and (s[pos] <= ' ') do Inc(pos); + if (pos > slen) then exit; + if (slen-pos = 1) and (s[pos] = '.') then exit; // single dot + // integral part + while (pos <= slen) do + begin + if (s[pos] < '0') or (s[pos] > '9') then break; + res := res*10+Byte(s[pos])-48; + Inc(pos); + end; + if (pos <= slen) then + begin + // must be a dot + if (s[pos] <> '.') then exit; + Inc(pos); + while (pos <= slen) do + begin + if (s[pos] < '0') or (s[pos] > '9') then break; + frac := frac/10; + res += frac*(Byte(s[pos])-48); + Inc(pos); + end; + end; + if (pos <= slen) then exit; // oops + result := true; +end; // ////////////////////////////////////////////////////////////////////////// // // <0: no arg; 0/1: true/false; 666: toggle -function conGetBoolArg (p: SArray; idx: Integer): Integer; +function conGetBoolArg (p: SSArray; idx: Integer): Integer; begin if (idx < 0) or (idx > High(p)) then begin result := -1; exit; end; result := 0; @@ -126,7 +205,7 @@ begin end; -procedure boolVarHandler (me: PCommand; p: SArray); +procedure boolVarHandler (me: PCommand; p: SSArray); procedure binaryFlag (var flag: Boolean; msg: AnsiString); begin if (Length(p) > 2) then @@ -137,11 +216,12 @@ procedure boolVarHandler (me: PCommand; p: SArray); begin case conGetBoolArg(p, 1) of -1: begin end; - 0: if conIsCheatsEnabled then flag := false else begin conwriteln('not available'); exit; end; - 1: if conIsCheatsEnabled then flag := true else begin conwriteln('not available'); exit; end; - 666: if conIsCheatsEnabled then flag := not flag else begin conwriteln('not available'); exit; end; + 0: if not me.cheat or conIsCheatsEnabled then flag := false else begin conwriteln('not available'); exit; end; + 1: if not me.cheat or conIsCheatsEnabled then flag := true else begin conwriteln('not available'); exit; end; + 666: if not me.cheat or conIsCheatsEnabled then flag := not flag else begin conwriteln('not available'); exit; end; end; - if flag then conwritefln('%s: tan', [msg]) else conwritefln('%s: ona', [msg]); + if (Length(msg) = 0) then msg := p[0] else msg += ':'; + if flag then conwritefln('%s tan', [msg]) else conwritefln('%s ona', [msg]); end; end; begin @@ -149,7 +229,42 @@ begin end; -procedure conRegVar (const conname: AnsiString; pvar: PBoolean; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false); overload; +procedure intVarHandler (me: PCommand; p: SSArray); + procedure binaryFlag (var flag: Boolean; msg: AnsiString); + begin + if (Length(p) > 2) then + begin + conwritefln('too many arguments to ''%s''', [p[0]]); + end + else + begin + case conGetBoolArg(p, 1) of + -1: begin end; + 0: if not me.cheat or conIsCheatsEnabled then flag := false else begin conwriteln('not available'); exit; end; + 1: if not me.cheat or conIsCheatsEnabled then flag := true else begin conwriteln('not available'); exit; end; + 666: if not me.cheat or conIsCheatsEnabled then flag := not flag else begin conwriteln('not available'); exit; end; + end; + if (Length(msg) = 0) then msg := p[0] else msg += ':'; + if flag then conwritefln('%s tan', [msg]) else conwritefln('%s ona', [msg]); + end; + end; +begin + if (Length(p) <> 2) then + begin + conwritefln('%s %d', [me.cmd, PInteger(me.ptr)^]); + end + else + begin + try + PInteger(me.ptr)^ := StrToInt(p[1]); + except + conwritefln('invalid integer value: "%s"', [p[1]]); + end; + end; +end; + + +procedure conRegVar (const conname: AnsiString; pvar: PBoolean; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload; var f: Integer; cp: PCommand; @@ -161,7 +276,26 @@ begin cp.proc := nil; cp.procEx := boolVarHandler; cp.help := ahelp; - cp.hidden := false; + cp.hidden := ahidden; + cp.ptr := pvar; + cp.msg := amsg; + cp.cheat := acheat; +end; + + +procedure conRegVar (const conname: AnsiString; pvar: PInteger; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload; +var + f: Integer; + cp: PCommand; +begin + f := Length(commands); + SetLength(commands, f+1); + cp := @commands[f]; + cp.cmd := LowerCase(conname); + cp.proc := nil; + cp.procEx := intVarHandler; + cp.help := ahelp; + cp.hidden := ahidden; cp.ptr := pvar; cp.msg := amsg; cp.cheat := acheat; @@ -177,44 +311,7 @@ type end; -procedure singleVarHandler (me: PCommand; p: SArray); - // poor man's floating literal parser; i'm sorry, but `StrToFloat()` sux cocks - function parseFloat (var res: Single; const s: AnsiString): Boolean; - var - pos: Integer = 1; - frac: Single = 1; - slen: Integer; - begin - result := false; - res := 0; - slen := Length(s); - while (slen > 0) and (s[slen] <= ' ') do Dec(slen); - while (pos <= slen) and (s[pos] <= ' ') do Inc(pos); - if (pos > slen) then exit; - if (slen-pos = 1) and (s[pos] = '.') then exit; // single dot - // integral part - while (pos <= slen) do - begin - if (s[pos] < '0') or (s[pos] > '9') then break; - res := res*10+Byte(s[pos])-48; - Inc(pos); - end; - if (pos <= slen) then - begin - // must be a dot - if (s[pos] <> '.') then exit; - Inc(pos); - while (pos <= slen) do - begin - if (s[pos] < '0') or (s[pos] > '9') then break; - frac := frac/10; - res += frac*(Byte(s[pos])-48); - Inc(pos); - end; - end; - if (pos <= slen) then exit; // oops - result := true; - end; +procedure singleVarHandler (me: PCommand; p: SSArray); var pv: PVarSingle; nv: Single; @@ -222,13 +319,13 @@ var begin if (Length(p) > 2) then begin - conwritefln('too many arguments to ''%s''', [p[0]]); + conwritefln('too many arguments to ''%s''', [me.cmd]); exit; end; pv := PVarSingle(me.ptr); if (Length(p) = 2) then begin - if not conIsCheatsEnabled then begin conwriteln('not available'); exit; end; + if me.cheat and (not conIsCheatsEnabled) then begin conwriteln('not available'); exit; end; if (CompareText(p[1], 'default') = 0) or (CompareText(p[1], 'def') = 0) or (CompareText(p[1], 'd') = 0) or (CompareText(p[1], 'off') = 0) or (CompareText(p[1], 'ona') = 0) then @@ -237,9 +334,9 @@ begin end else begin - if not parseFloat(nv, p[1]) then + if not conParseFloat(nv, p[1]) then begin - conwritefln('%s: ''%s'' doesn''t look like a floating number', [p[0], p[1]]); + conwritefln('%s: ''%s'' doesn''t look like a floating number', [me.cmd, p[1]]); exit; end; if (nv < pv.min) then nv := pv.min; @@ -248,18 +345,18 @@ begin end; end; msg := me.msg; - if (Length(msg) = 0) then msg := p[0] else msg += ':'; + if (Length(msg) = 0) then msg := me.cmd else msg += ':'; conwritefln('%s %s', [msg, pv.val^]); end; -procedure conRegVar (const conname: AnsiString; pvar: PSingle; amin, amax: Single; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false); overload; +procedure conRegVar (const conname: AnsiString; pvar: PSingle; amin, amax: Single; const ahelp: AnsiString; const amsg: AnsiString; acheat: Boolean=false; ahidden: Boolean=false); overload; var f: Integer; cp: PCommand; pv: PVarSingle; begin - GetMem(pv, sizeof(pv^)); + GetMem(pv, sizeof(TVarSingle)); pv.val := pvar; pv.min := amin; pv.max := amax; @@ -271,7 +368,7 @@ begin cp.proc := nil; cp.procEx := singleVarHandler; cp.help := ahelp; - cp.hidden := false; + cp.hidden := ahidden; cp.ptr := pv; cp.msg := amsg; cp.cheat := acheat; @@ -294,7 +391,7 @@ begin end; end; -function ParseAlias(Str: AnsiString): SArray; +function ParseAlias(Str: AnsiString): SSArray; begin Result := nil; @@ -310,11 +407,11 @@ begin end; end; -procedure ConsoleCommands(p: SArray); +procedure ConsoleCommands(p: SSArray); var cmd, s: AnsiString; a, b: Integer; - F: TextFile; + (* F: TextFile; *) begin cmd := LowerCase(p[0]); s := ''; @@ -416,53 +513,22 @@ begin if cmd = 'exec' then begin // exec - if Length(p) > 1 then + if Length(p) = 2 then begin - s := GameDir+'/'+p[1]; - - {$I-} - AssignFile(F, s); - Reset(F); - if IOResult <> 0 then - begin - g_Console_Add(Format(_lc[I_CONSOLE_ERROR_READ], [s])); - CloseFile(F); - Exit; - end; - g_Console_Add(Format(_lc[I_CONSOLE_EXEC], [s])); - - while not EOF(F) do - begin - ReadLn(F, s); - if IOResult <> 0 then - begin - g_Console_Add(Format(_lc[I_CONSOLE_ERROR_READ], [s])); - CloseFile(F); - Exit; - end; - if Pos('#', s) <> 1 then // script comment - begin - // prevents endless loops - Inc(RecursionDepth); - RecursionLimitHit := (RecursionDepth > MaxScriptRecursion) or RecursionLimitHit; - if not RecursionLimitHit then - g_Console_Process(s, True); - Dec(RecursionDepth); - end; - end; - if (RecursionDepth = 0) and RecursionLimitHit then - begin - g_Console_Add(Format(_lc[I_CONSOLE_ERROR_CALL], [s])); - RecursionLimitHit := False; - end; - - CloseFile(F); - {$I+} + s := GameDir + '/' + p[1]; + g_Console_ReadConfig(s); end else g_Console_Add('exec