Commit 03898538 authored by Steven Fuller's avatar Steven Fuller

Added keyboard! Fixed some bugs, especially the shareware graphic numbers

parent 4e4d87ec
...@@ -46,18 +46,19 @@ included now (if ever) ...@@ -46,18 +46,19 @@ included now (if ever)
data in vga memory. so figure it out, fix it, and remove data in vga memory. so figure it out, fix it, and remove
* especially with the video functions, there are functions/defines which * especially with the video functions, there are functions/defines which
just call a different function (most are left from the update block code) just call a different function (most are left from the update block code)
remove them rename/remove them
* implement fizzlefade, and get that last pixel! * implement fizzlefade, and get that last pixel!
* fix wl_debug.c, lots of junk code.. * fix wl_debug.c, lots of junk code..
* change the current parameter handling code to something like getopt * change the current parameter handling code to something like getopt
* urgent: fix input (event handling), so that it makes sense * urgent: fix input (event handling), so that it makes sense
* wl_menu.c does loops on Keyboard. should call id_in functions instead * wl_menu.c does loops on Keyboard. should call id_in functions instead
* rename goobers to debugmode, then remove debugmode for things...
* for some reason, it feels sluggish, maybe its from having mikmod playing
at the same time...
* look for places where gfx needs to be redrawn, like back to game etc
Specific: Specific:
* memory/sound intro screen goes * memory/sound intro screen goes
- trademarked images, only came with wolf3d 1.4's (I believe) - Trademarked images, only came with wolf3d 1.4's (I believe)
* copy protection goes * copy protection goes
- Who needs a manual to look at the source? - Who needs a manual to look at the source?
* put event handling in id_in.c
- Most loops which take too long call some input function and can place a
function call in the rest of the loops
This diff is collapsed.
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <math.h> #include <math.h>
#include <vga.h> #include <vga.h>
#include <vgakeyboard.h>
#include "misc.h" #include "misc.h"
......
...@@ -151,6 +151,64 @@ static void INL_KeyService(void) ...@@ -151,6 +151,64 @@ static void INL_KeyService(void)
} }
} }
void keyboard_handler(int code, int press)
{
static boolean special;
byte k, c, temp;
int i;
/* k = inportb(0x60); // Get the scan code */
k = code;
if (k == 0xe0) // Special key prefix
special = true;
else if (k == 0xe1) // Handle Pause key
Paused = true;
else
{
if (press == 0)
{
// DEBUG - handle special keys: ctl-alt-delete, print scrn
Keyboard[k] = false;
}
else // Make code
{
LastCode = CurCode;
CurCode = LastScan = k;
Keyboard[k] = true;
if (special)
c = SpecialNames[k];
else
{
if (k == sc_CapsLock)
{
CapsLock ^= true;
}
if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted
{
c = ShiftNames[k];
if ((c >= 'A') && (c <= 'Z') && CapsLock)
c += 'a' - 'A';
}
else
{
c = ASCIINames[k];
if ((c >= 'a') && (c <= 'z') && CapsLock)
c -= 'a' - 'A';
}
}
if (c)
LastASCII = c;
}
special = false;
}
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// //
// INL_GetMouseDelta() - Gets the amount that the mouse has moved from the // INL_GetMouseDelta() - Gets the amount that the mouse has moved from the
...@@ -215,6 +273,8 @@ static word INL_GetJoyButtons(word joy) ...@@ -215,6 +273,8 @@ static word INL_GetJoyButtons(word joy)
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
static void INL_StartKbd(void) static void INL_StartKbd(void)
{ {
keyboard_init();
keyboard_seteventhandler(keyboard_handler);
IN_ClearKeysDown(); IN_ClearKeysDown();
} }
...@@ -225,6 +285,7 @@ static void INL_StartKbd(void) ...@@ -225,6 +285,7 @@ static void INL_StartKbd(void)
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
static void INL_ShutKbd(void) static void INL_ShutKbd(void)
{ {
keyboard_close();
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
...@@ -366,6 +427,8 @@ void IN_ReadControl(int player,ControlInfo *info) ...@@ -366,6 +427,8 @@ void IN_ReadControl(int player,ControlInfo *info)
mx = my = motion_None; mx = my = motion_None;
buttons = 0; buttons = 0;
keyboard_update();
switch (type = Controls[player]) switch (type = Controls[player])
{ {
case ctrl_Keyboard: case ctrl_Keyboard:
...@@ -460,13 +523,20 @@ void IN_StartAck(void) ...@@ -460,13 +523,20 @@ void IN_StartAck(void)
btnstate[i] = true; btnstate[i] = true;
} }
int flipz;
boolean IN_CheckAck (void) boolean IN_CheckAck (void)
{ {
unsigned i,buttons; unsigned i,buttons;
// if (flipz == 1) {
// see if something has been pressed flipz = 0;
// return false;
}
flipz++;
while (keyboard_update()) ; /* get all events */
if (LastScan) if (LastScan)
return true; return true;
...@@ -490,7 +560,7 @@ void IN_Ack (void) ...@@ -490,7 +560,7 @@ void IN_Ack (void)
{ {
IN_StartAck (); IN_StartAck ();
return; /* TODO: fix when keyboard implemented */ // return; /* TODO: fix when keyboard implemented */
while (!IN_CheckAck ()) ; while (!IN_CheckAck ()) ;
} }
......
...@@ -1090,20 +1090,24 @@ void PlayDemoFromFile(char *demoname) ...@@ -1090,20 +1090,24 @@ void PlayDemoFromFile(char *demoname)
#define DEATHROTATE 2 #define DEATHROTATE 2
void Died (void) void Died()
{ {
float fangle; float fangle;
long dx,dy; long dx,dy;
int iangle,curangle,clockwise,counter,change; int iangle,curangle,clockwise,counter,change;
gamestate.weapon = -1; // take away weapon gamestate.weapon = -1; // take away weapon
SD_PlaySound (PLAYERDEATHSND); SD_PlaySound(PLAYERDEATHSND);
//
// swing around to face attacker /* swing around to face attacker (if any) */
// if (killerobj) {
dx = killerobj->x - player->x; dx = killerobj->x - player->x;
dy = player->y - killerobj->y; dy = player->y - killerobj->y;
} else {
dx = -player->x;
dy = player->y;
}
fangle = atan2(dy,dx); // returns -pi to pi fangle = atan2(dy,dx); // returns -pi to pi
if (fangle<0) if (fangle<0)
fangle = M_PI*2+fangle; fangle = M_PI*2+fangle;
......
...@@ -496,8 +496,6 @@ void LevelCompleted (void) ...@@ -496,8 +496,6 @@ void LevelCompleted (void)
#endif #endif
}; };
CacheLump(LEVELEND_LUMP_START,LEVELEND_LUMP_END); CacheLump(LEVELEND_LUMP_START,LEVELEND_LUMP_END);
ClearSplitVWB (); // set up for double buffering in split screen ClearSplitVWB (); // set up for double buffering in split screen
VWB_Bar (0,0,320,200-STATUSLINES,127); VWB_Bar (0,0,320,200-STATUSLINES,127);
...@@ -862,10 +860,10 @@ void LevelCompleted (void) ...@@ -862,10 +860,10 @@ void LevelCompleted (void)
boolean PreloadUpdate(unsigned current, unsigned total) boolean PreloadUpdate(unsigned current, unsigned total)
{ {
unsigned w = WindowW - 10; int w = WindowW - 10;
VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w,2,BLACK); VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w,2,BLACK);
w = ((long)w * current) / total; w = (w * current) / total;
if (w) { if (w) {
VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w,2,0x37); VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w,2,0x37);
VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w-1,1,0x32); VWB_Bar(WindowX + 5,WindowY + WindowH - 3,w-1,1,0x32);
...@@ -875,28 +873,28 @@ boolean PreloadUpdate(unsigned current, unsigned total) ...@@ -875,28 +873,28 @@ boolean PreloadUpdate(unsigned current, unsigned total)
return false; return false;
} }
void PreloadGraphics(void) void PreloadGraphics()
{ {
DrawLevel(); DrawLevel();
ClearSplitVWB(); ClearSplitVWB();
VWB_Bar (0,0,320,200-STATUSLINES,127); VWB_Bar(0,0,320,200-STATUSLINES,127);
LatchDrawPic (20-14,80-3*8,GETPSYCHEDPIC); VWB_DrawPic(48, 56, GETPSYCHEDPIC);
WindowX = 160-14*8; WindowX = 160-14*8;
WindowY = 80-3*8; WindowY = 80-3*8;
WindowW = 28*8; WindowW = 28*8;
WindowH = 48; WindowH = 48;
VW_UpdateScreen(); VW_UpdateScreen();
VW_FadeIn (); VW_FadeIn();
PM_Preload((void *)PreloadUpdate); PM_Preload((void *)PreloadUpdate);
IN_UserInput (70); IN_UserInput (70);
VW_FadeOut (); VW_FadeOut();
DrawPlayBorder (); DrawPlayBorder();
VW_UpdateScreen (); VW_UpdateScreen();
} }
...@@ -923,7 +921,6 @@ void DrawHighScores(void) ...@@ -923,7 +921,6 @@ void DrawHighScores(void)
MM_SortMem (); MM_SortMem ();
#ifndef SPEAR #ifndef SPEAR
// CA_CacheGrChunk (C_CODEPIC);
CA_CacheGrChunk (HIGHSCORESPIC); CA_CacheGrChunk (HIGHSCORESPIC);
CA_CacheGrChunk (STARTFONT); CA_CacheGrChunk (STARTFONT);
CA_CacheGrChunk (C_LEVELPIC); CA_CacheGrChunk (C_LEVELPIC);
...@@ -939,9 +936,7 @@ void DrawHighScores(void) ...@@ -939,9 +936,7 @@ void DrawHighScores(void)
VWB_DrawPic(4*8,68,C_NAMEPIC); VWB_DrawPic(4*8,68,C_NAMEPIC);
VWB_DrawPic(20*8,68,C_LEVELPIC); VWB_DrawPic(20*8,68,C_LEVELPIC);
VWB_DrawPic(28*8,68,C_SCOREPIC); VWB_DrawPic(28*8,68,C_SCOREPIC);
#ifndef UPLOAD
// VWB_DrawPic(35*8,68,C_CODEPIC);
#endif
fontnumber=0; fontnumber=0;
#else #else
......
...@@ -49,7 +49,7 @@ int shootdelta; // pixels away from centerx a ta ...@@ -49,7 +49,7 @@ int shootdelta; // pixels away from centerx a ta
fixed scale,maxslope; fixed scale,maxslope;
long heightnumerator; long heightnumerator;
void Quit (char *error); void Quit(char *error);
boolean startgame,loadedgame; boolean startgame,loadedgame;
int mouseadjustment; int mouseadjustment;
...@@ -644,6 +644,7 @@ void SignonScreen() ...@@ -644,6 +644,7 @@ void SignonScreen()
{ {
VL_SetPalette(&gamepal); VL_SetPalette(&gamepal);
VL_MemToScreen(&introscn, 320, 200, 0, 0); VL_MemToScreen(&introscn, 320, 200, 0, 0);
VW_UpdateScreen();
} }
...@@ -667,7 +668,8 @@ void FinishSignon (void) ...@@ -667,7 +668,8 @@ void FinishSignon (void)
SETFONTCOLOR(14,4); SETFONTCOLOR(14,4);
US_CPrint ("Press a key"); US_CPrint ("Press a key");
VW_UpdateScreen();
if (!NoWait) if (!NoWait)
IN_Ack (); IN_Ack ();
...@@ -677,7 +679,8 @@ void FinishSignon (void) ...@@ -677,7 +679,8 @@ void FinishSignon (void)
SETFONTCOLOR(10,4); SETFONTCOLOR(10,4);
US_CPrint ("Working..."); US_CPrint ("Working...");
VW_UpdateScreen();
SETFONTCOLOR(0,15); SETFONTCOLOR(0,15);
#else #else
if (!NoWait) if (!NoWait)
...@@ -1147,52 +1150,31 @@ void NewViewSize(int width) ...@@ -1147,52 +1150,31 @@ void NewViewSize(int width)
========================== ==========================
*/ */
void Quit (char *error) void Quit(char *error)
{ {
memptr screen; memptr screen = NULL;
if (!*error) if (error && !*error) {
{ CA_CacheGrChunk(ORDERSCREEN);
CA_CacheGrChunk(ORDERSCREEN); screen = grsegs[ORDERSCREEN];
screen = grsegs[ORDERSCREEN]; WriteConfig();
WriteConfig (); } else if (error) {
} CA_CacheGrChunk(ERRORSCREEN);
else screen = grsegs[ERRORSCREEN];
{
CA_CacheGrChunk(ERRORSCREEN);
screen = grsegs[ERRORSCREEN];
} }
ShutdownId (); ShutdownId();
if (screen) { if (screen) {
/* blah blah */ /* blah blah */
} }
if (error && *error) if (error && *error) {
printf("Quit: %s\n", error); printf("Quit: %s\n", error);
else exit(EXIT_FAILURE);
printf("Quit: Nothing\n");
#if 0
if (error && *error)
{
movedata ((unsigned)screen,7,0xb800,0,7*160);
gotoxy (10,4);
puts(error);
gotoxy (1,8);
exit(1);
}
else
if (!error || !(*error))
{
clrscr();
movedata ((unsigned)screen,7,0xb800,0,4000);
gotoxy(1,24);
} }
#endif
exit(EXIT_SUCCESS);
exit(0);
} }
//=========================================================================== //===========================================================================
......
...@@ -234,7 +234,6 @@ void US_ControlPanel(byte scancode) ...@@ -234,7 +234,6 @@ void US_ControlPanel(byte scancode)
{ {
int which,i,start; int which,i,start;
if (ingame) if (ingame)
if (CP_CheckQuick(scancode)) if (CP_CheckQuick(scancode))
return; return;
...@@ -331,7 +330,7 @@ void US_ControlPanel(byte scancode) ...@@ -331,7 +330,7 @@ void US_ControlPanel(byte scancode)
VL_FadeIn(0,255,grsegs[IDGUYSPALETTE],30); VL_FadeIn(0,255,grsegs[IDGUYSPALETTE],30);
UNCACHEGRCHUNK(IDGUYSPALETTE); UNCACHEGRCHUNK(IDGUYSPALETTE);
while (Keyboard[sc_I] || Keyboard[sc_D]); while (Keyboard[sc_I] || Keyboard[sc_D]) IN_CheckAck();
IN_ClearKeysDown(); IN_ClearKeysDown();
IN_Ack(); IN_Ack();
...@@ -421,7 +420,7 @@ void US_ControlPanel(byte scancode) ...@@ -421,7 +420,7 @@ void US_ControlPanel(byte scancode)
} }
// RETURN/START GAME EXECUTION // RETURN/START GAME EXECUTION
#ifdef SPEAR #ifdef SPEAR
UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END); UnCacheLump (OPTIONS_LUMP_START,OPTIONS_LUMP_END);
MM_SortMem (); MM_SortMem ();
...@@ -1468,12 +1467,12 @@ int CalibrateJoystick(void) ...@@ -1468,12 +1467,12 @@ int CalibrateJoystick(void)
do do
{ {
jb=IN_JoyButtons(); jb=IN_JoyButtons();
IN_CheckAck(); /* TODO: force update */
if (Keyboard[sc_Escape]) if (Keyboard[sc_Escape])
return 0; return 0;
#ifndef SPEAR
if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers")) if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))
PicturePause(); PicturePause();
#endif
} while(!(jb&1)); } while(!(jb&1));
...@@ -1499,12 +1498,11 @@ int CalibrateJoystick(void) ...@@ -1499,12 +1498,11 @@ int CalibrateJoystick(void)
do do
{ {
jb=IN_JoyButtons(); jb=IN_JoyButtons();
IN_CheckAck(); /* TODO: force update */
if (Keyboard[sc_Escape]) if (Keyboard[sc_Escape])
return 0; return 0;
#ifndef SPEAR
if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers")) if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))
PicturePause(); PicturePause();
#endif
} while(!(jb&2)); } while(!(jb&2));
IN_GetJoyAbs(joystickport,&xmax,&ymax); IN_GetJoyAbs(joystickport,&xmax,&ymax);
...@@ -1654,7 +1652,7 @@ void MouseSensitivity(void) ...@@ -1654,7 +1652,7 @@ void MouseSensitivity(void)
VWB_Bar(61+20*mouseadjustment,98,19,9,READHCOLOR); VWB_Bar(61+20*mouseadjustment,98,19,9,READHCOLOR);
VW_UpdateScreen(); VW_UpdateScreen();
SD_PlaySound(MOVEGUN1SND); SD_PlaySound(MOVEGUN1SND);
while(Keyboard[sc_LeftArrow]); while(Keyboard[sc_LeftArrow]) IN_CheckAck();
WaitKeyUp(); WaitKeyUp();
} }
break; break;
...@@ -1670,7 +1668,7 @@ void MouseSensitivity(void) ...@@ -1670,7 +1668,7 @@ void MouseSensitivity(void)
VWB_Bar(61+20*mouseadjustment,98,19,9,READHCOLOR); VWB_Bar(61+20*mouseadjustment,98,19,9,READHCOLOR);
VW_UpdateScreen(); VW_UpdateScreen();
SD_PlaySound(MOVEGUN1SND); SD_PlaySound(MOVEGUN1SND);
while(Keyboard[sc_RightArrow]); while(Keyboard[sc_RightArrow]) IN_CheckAck();
WaitKeyUp(); WaitKeyUp();
} }
break; break;
...@@ -1678,11 +1676,7 @@ void MouseSensitivity(void) ...@@ -1678,11 +1676,7 @@ void MouseSensitivity(void)
break; break;
} }
#ifndef SPEAR
if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))
#else
if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("debugmode")) if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("debugmode"))
#endif
PicturePause(); PicturePause();
if (ci.button0 || Keyboard[sc_Space] || Keyboard[sc_Enter]) if (ci.button0 || Keyboard[sc_Space] || Keyboard[sc_Enter])
...@@ -1942,7 +1936,8 @@ void EnterCtrlData(int index,CustomCtrls *cust,void (*DrawRtn)(int),void (*Print ...@@ -1942,7 +1936,8 @@ void EnterCtrlData(int index,CustomCtrls *cust,void (*DrawRtn)(int),void (*Print
do do
{ {
int button,result=0; int button,result=0;
IN_CheckAck(); /* force update */
if (type==KEYBOARDBTNS||type==KEYBOARDMOVE) if (type==KEYBOARDBTNS||type==KEYBOARDMOVE)
IN_ClearKeysDown(); IN_ClearKeysDown();
...@@ -2459,11 +2454,7 @@ void CP_ChangeView(void) ...@@ -2459,11 +2454,7 @@ void CP_ChangeView(void)
break; break;
} }
#ifndef SPEAR
if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))
#else
if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("debugmode")) if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("debugmode"))
#endif
PicturePause(); PicturePause();
if (ci.button0 || Keyboard[sc_Enter]) if (ci.button0 || Keyboard[sc_Enter])
...@@ -3152,6 +3143,7 @@ int Confirm(char *string) ...@@ -3152,6 +3143,7 @@ int Confirm(char *string)
do do
{ {
IN_CheckAck(); /* TODO: force update */
if (get_TimeCount() >= 10) if (get_TimeCount() >= 10)
{ {
switch(tick) switch(tick)
...@@ -3169,10 +3161,8 @@ int Confirm(char *string) ...@@ -3169,10 +3161,8 @@ int Confirm(char *string)
set_TimeCount(0); set_TimeCount(0);
} }
#ifndef SPEAR
if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers")) if (Keyboard[sc_Tab] && Keyboard[sc_P] && MS_CheckParm("goobers"))
PicturePause(); PicturePause();
#endif
} while(!Keyboard[sc_Y] && !Keyboard[sc_N] && !Keyboard[sc_Escape]); } while(!Keyboard[sc_Y] && !Keyboard[sc_N] && !Keyboard[sc_Escape]);
...@@ -3182,7 +3172,7 @@ int Confirm(char *string) ...@@ -3182,7 +3172,7 @@ int Confirm(char *string)
ShootSnd(); ShootSnd();
} }
while(Keyboard[sc_Y] || Keyboard[sc_N] || Keyboard[sc_Escape]); while(Keyboard[sc_Y] || Keyboard[sc_N] || Keyboard[sc_Escape]) IN_CheckAck();
IN_ClearKeysDown(); IN_ClearKeysDown();
SD_PlaySound(whichsnd[xit]); SD_PlaySound(whichsnd[xit]);
......
...@@ -479,6 +479,10 @@ void PollControls (void) ...@@ -479,6 +479,10 @@ void PollControls (void)
// //
// get button states // get button states
// //
/* Update keys */
IN_CheckAck(); /* TODO: better name */
PollKeyboardButtons (); PollKeyboardButtons ();
if (mouseenabled) if (mouseenabled)
...@@ -731,9 +735,10 @@ void CheckKeys (void) ...@@ -731,9 +735,10 @@ void CheckKeys (void)
ClearMemory (); ClearMemory ();
ClearSplitVWB (); ClearSplitVWB ();
US_ControlPanel(scan); US_ControlPanel(scan);
DrawAllPlayBorderSides (); DrawAllPlayBorderSides ();
VW_UpdateScreen();
if (scan == sc_F9) if (scan == sc_F9)
StartMusic (); StartMusic ();
...@@ -753,6 +758,8 @@ void CheckKeys (void) ...@@ -753,6 +758,8 @@ void CheckKeys (void)
SETFONTCOLOR(0,15); SETFONTCOLOR(0,15);
IN_ClearKeysDown(); IN_ClearKeysDown();
DrawPlayScreen (); DrawPlayScreen ();
VW_UpdateScreen();
if (!startgame && !loadedgame) if (!startgame && !loadedgame)
{ {
VW_FadeIn (); VW_FadeIn ();
...@@ -815,8 +822,6 @@ next element. ...@@ -815,8 +822,6 @@ next element.
========================= =========================
*/ */
int objcount;
void InitActorList (void) void InitActorList (void)
{ {
int i; int i;
...@@ -835,8 +840,6 @@ void InitActorList (void) ...@@ -835,8 +840,6 @@ void InitActorList (void)
objfreelist = &objlist[0]; objfreelist = &objlist[0];
lastobj = NULL; lastobj = NULL;
objcount = 0;
// //
// give the player the first free spots // give the player the first free spots
// //
...@@ -876,8 +879,6 @@ void GetNewActor (void) ...@@ -876,8 +879,6 @@ void GetNewActor (void)
new->active = false; new->active = false;
lastobj = new; lastobj = new;
objcount++;
} }
//=========================================================================== //===========================================================================
...@@ -921,7 +922,6 @@ void RemoveObj (objtype *gone) ...@@ -921,7 +922,6 @@ void RemoveObj (objtype *gone)
gone->prev = objfreelist; gone->prev = objfreelist;
objfreelist = gone; objfreelist = gone;
objcount--;
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment