diff --git a/package/common/gamecontrollerdb.txt b/package/common/gamecontrollerdb.txt index 97dd5c0c7..78d3bdf8b 100644 --- a/package/common/gamecontrollerdb.txt +++ b/package/common/gamecontrollerdb.txt @@ -1,18 +1,44 @@ -# Game Controller DB for SDL in 2.0.9 format +# Game Controller DB for SDL in 2.0.10 format # Source: https://github.com/gabomdq/SDL_GameControllerDB # Windows 03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, 03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000011ab000000000000,8BitDo F30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00015900000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00065280000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000060000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000061000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00003028000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00006228000000000000,8BitDo SN30 GP,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000031000000000000,8BitDo Wireless Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, 030000008f0e00001200000000000000,Acme GA-02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 03000000fa190000f0ff000000000000,Acteck AGJ-3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000006f0e00001413000000000000,Afterglow,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -21,6 +47,7 @@ 030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000d62000001d57000000000000,Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000869800002400000000007801,Astro C40 TR,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000d6200000e557000000000000,Batarang,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, 030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -38,6 +65,7 @@ 0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, 03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, 03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e040000a102000000000000,Controller (Xbox 360 Wireless Receiver for Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 030000005e040000ff02000000000000,Controller (Xbox One For Windows) - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, @@ -50,6 +78,7 @@ 030000006f0e00003001000000000000,EA SPORTS PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, 03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, 03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 03000000852100000201000000000000,FF-GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -83,6 +112,7 @@ 030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, 03000000632500002605000000000000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, @@ -90,9 +120,11 @@ 030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f0000c100000000000000,Horipad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, 030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows, @@ -138,9 +170,13 @@ 03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, 03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, 03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, 0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, 03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000790000002418000000000000,Mega Drive,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows, 03000000380700006382000000000000,MLG GamePad PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, 03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, @@ -191,6 +227,8 @@ 03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000321500000204000000000000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000321500000104000000000000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, 030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -221,14 +259,16 @@ 03000000a30600002106000000000000,Saitek PS1000,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000a306000020f6000000000000,Saitek PS2700,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000300f00001101000000000000,Saitek Rumble Pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, 0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, 030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -# 030000005e0400008e02000000007801,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400008e02000000007801,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00000908000000000000,SL-6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000008f0e00000800000000000000,SpeedLink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, 03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows, 03000000790000001c18000000000000,STK-7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows, @@ -247,6 +287,7 @@ 03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows, 03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000006e0500001320000000000000,U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000300f00000701000000000000,USB 4-Axis 12-Button Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 03000000341a00002308000000000000,USB gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, @@ -256,7 +297,9 @@ 03000000f0250000c183000000000000,USB gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000ff1100004133000000000000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, 03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000790000001a18000000000000,Venom,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00000302000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, @@ -267,10 +310,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, # Mac OS X 030000008f0e00000300000009010000,2In1 USB Joystick,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000031000001000000,8BitDo Wireless Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000a00500003232000009010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, @@ -282,6 +329,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 030000006f0e00000102000000000000,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -302,6 +350,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 030000006d04000018c2000000010000,Logitech RumblePad 2 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -310,14 +359,19 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000380700008433000000010000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000380700008483000000010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X, +0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, 03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, 03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, +03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X, 030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X, 030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c050000da0c000000010000,Playstation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, 030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, @@ -329,6 +383,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000321500000204000000010000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000321500000104000000010000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, 03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -336,6 +391,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000c6240000fefa000000000000,Rock Candy Gamepad for PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Mac OS X, 03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, 03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, 030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, @@ -353,6 +409,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, +030000006f0e00000302000025040000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000791d00000103000009010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, 050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, 030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -370,37 +428,57 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, # Linux 05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, 03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000061000000010000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, 05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +030000005e0400008e02000020010000,8BitDo Wireless Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c82d00000031000011010000,8BitDo Wireless Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 030000006f0e00001302000000010000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00003901000020060000,Afterglow Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00003901000013020000,Afterglow Prismatic Wired Controller 048-007-NA,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, 030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003901000013020000,Afterglow Prismatic Wired Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, 05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, 03000000120c00000500000010010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, 03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, +03000000ffff0000ffff000000010000,Chinese-made Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, 03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux, 03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux, 03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, 03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, +030000004f04000004b3000010010000,Dual Power 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, 03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000008f0e00000800000010010000,Gasia Co. Ltd PS(R) Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000007d0400000540000000010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, @@ -408,6 +486,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux, 030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, 03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, @@ -428,6 +507,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, 050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000d80400008200000003000000,IMS PCU#0 Gamepad Interface,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux, 03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, 0500000049190000020400001b010000,Ipega PG-9069 - Bluetooth Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, @@ -463,10 +543,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -0300000079000000d218000011010000,MAGIC-NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, 03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, 03000000790000004318000010010000,Mayflash GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, +0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 0300000025090000e803000001010000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, 03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, @@ -478,12 +560,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, 030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +03000000c62400001a53000000010000,Mini PE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, 05000000d6200000e589000001000000,Moga 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, 05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, 05000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, 03000000250900006688000000010000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, 030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux, +030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, 050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, 05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, @@ -498,9 +583,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, @@ -510,7 +597,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, 060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, @@ -521,6 +608,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, @@ -533,6 +621,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000321500000204000011010000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 03000000321500000104000011010000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -540,6 +629,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux, 0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, 030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00001f01000000010000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -548,9 +638,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, 03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, 03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, +03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b0,y:b1,platform:Linux, 03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, 03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux, 03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux, 03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux, 03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000632500007505000010010000,SHANWAN PS3/PC Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, @@ -582,11 +674,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000004f04000012b3000010010000,Thrustmaster vibrating gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, 03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, 03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, +030000006f0e00000302000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000791d00000103000010010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -596,9 +692,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, 030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000ea02000001030000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e040000ea02000001030000,Xbox One Wireless Controller (Model 1708),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux, 03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, @@ -619,6 +717,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, 050000004c050000cc090000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, 35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, 05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, @@ -630,9 +730,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, # iOS 05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, +05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, +05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, 05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, +05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, +050000004c050000cc090000df070000,DUALSHOCK 4 Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, 4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, 4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, 05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, +05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, 05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, 05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, +050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 0874299e1..e52c18102 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -623,6 +623,7 @@ file( GLOB HEADER_FILES common/console/*.h common/filesystem/*.h common/music/*.h + common/menu/*.h build/src/*.h thirdparty/include/*.h @@ -664,9 +665,9 @@ set( FASTMATH_SOURCES set (PCH_SOURCES + audiolib/src/drivers.cpp audiolib/src/driver_adlib.cpp - audiolib/src/driver_nosound.cpp audiolib/src/driver_sdl.cpp audiolib/src/driver_winmm.cpp audiolib/src/formats.cpp @@ -746,11 +747,11 @@ set (PCH_SOURCES common/searchpaths.cpp common/initfs.cpp common/openaudio.cpp - common/optionmenu/optionmenu.cpp common/statistics.cpp common/secrets.cpp common/compositesavegame.cpp common/savegamehelp.cpp + common/quotes.cpp common/2d/v_2ddrawer.cpp common/2d/v_draw.cpp @@ -772,6 +773,7 @@ set (PCH_SOURCES common/console/c_commandline.cpp common/console/c_dispatch.cpp common/console/d_event.cpp + common/console/c_con.cpp common/utility/i_time.cpp common/utility/name.cpp @@ -788,6 +790,7 @@ set (PCH_SOURCES common/utility/m_png.cpp common/utility/memarena.cpp common/utility/sc_man.cpp + common/utility/stringtable.cpp common/utility/stats.cpp common/filesystem/filesystem.cpp @@ -824,7 +827,16 @@ set (PCH_SOURCES common/music/backend/oalsound.cpp common/music/backend/i_sound.cpp - + common/menu/imagescroller.cpp + common/menu/joystickmenu.cpp + common/menu/listmenu.cpp + common/menu/savegamemanager.cpp + common/menu/loadsavemenu.cpp + common/menu/menu.cpp + common/menu/menudef.cpp + common/menu/menuinput.cpp + common/menu/messagebox.cpp + common/menu/optionmenu.cpp ) if( MSVC ) @@ -848,7 +860,7 @@ add_executable( demolition WIN32 MACOSX_BUNDLE #zzautozend.cpp ) -set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${DEM_FASTMATH_FLAG} ) +#set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${DEM_FASTMATH_FLAG} ) set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" ) set_source_files_properties( utility/sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" ) set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE ) @@ -887,6 +899,8 @@ include_directories( common/textures common/filesystem common/music + common/dobject + common/menu platform ${CMAKE_BINARY_DIR}/libraries/gdtoa @@ -995,6 +1009,8 @@ source_group("Code\\Console" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/co source_group("Code\\Fonts" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/fonts/.+") source_group("Code\\File System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/.+") source_group("Code\\Music" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/music/.+") +source_group("Code\\DObject" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/dobject/.+") +source_group("Code\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/menu/.+") source_group("Utility\\Audiolib" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/.+") source_group("Utility\\Audiolib Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/include/.+") source_group("Utility\\Audiolib Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/src/.+") diff --git a/source/audiolib/include/al_midi.h b/source/audiolib/include/al_midi.h index f49d6058a..1dbb1608a 100644 --- a/source/audiolib/include/al_midi.h +++ b/source/audiolib/include/al_midi.h @@ -39,7 +39,7 @@ typedef struct extern AdLibTimbre ADLIB_TimbreBank[256]; opl3_chip *AL_GetChip(void); -void AL_RegisterTimbreBank(uint8_t *timbres); +void AL_RegisterTimbreBank(uint8_t const *timbres); void AL_SetStereo(int const stereo); #endif diff --git a/source/audiolib/include/opl3_reg.h b/source/audiolib/include/opl3_reg.h new file mode 100644 index 000000000..2396706d6 --- /dev/null +++ b/source/audiolib/include/opl3_reg.h @@ -0,0 +1,144 @@ +/* + * Copyright by Hannu Savolainen 1993-1996 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +// heavily modified for audiolib +// original definitions found at http://www.cs.albany.edu/~sdc/Linux/linux-2.0/drivers/sound/opl3.h +// it's from old Linux source but the license is pretty clearly 2-clause BSD. + +#ifndef opl3_reg_h__ +#define OPL3_opl3_reg_h__ + +#define OPL3_TEST_REGISTER 0x01 +#define OPL3_ENABLE_WAVE_SELECT 0x20 + +#define OPL3_TIMER1_REGISTER 0x02 +#define OPL3_TIMER2_REGISTER 0x03 +#define OPL3_TIMER_CONTROL_REGISTER 0x04 /* Left side */ +#define OPL3_IRQ_RESET 0x80 +#define OPL3_TIMER1_MASK 0x40 +#define OPL3_TIMER2_MASK 0x20 +#define OPL3_TIMER1_START 0x01 +#define OPL3_TIMER2_START 0x02 + +#define OPL3_CONNECTION_SELECT_REGISTER 0x04 /* Right side */ +#define OPL3_RIGHT_4OP_0 0x01 +#define OPL3_RIGHT_4OP_1 0x02 +#define OPL3_RIGHT_4OP_2 0x04 +#define OPL3_LEFT_4OP_0 0x08 +#define OPL3_LEFT_4OP_1 0x10 +#define OPL3_LEFT_4OP_2 0x20 + +#define OPL3_MODE_REGISTER 0x05 /* Right side */ +#define OPL3_ENABLE 0x01 +#define OPL3_OPL4_ENABLE 0x02 + +#define OPL3_KBD_SPLIT_REGISTER 0x08 /* Left side */ +#define OPL3_COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */ +#define OPL3_KEYBOARD_SPLIT 0x40 + +#define OPL3_PERCUSSION_REGISTER 0xbd /* Left side only */ +#define OPL3_TREMOLO_DEPTH 0x80 +#define OPL3_VIBRATO_DEPTH 0x40 +#define OPL3_PERCUSSION_ENABLE 0x20 +#define OPL3_BASSDRUM_ON 0x10 +#define OPL3_SNAREDRUM_ON 0x08 +#define OPL3_TOMTOM_ON 0x04 +#define OPL3_CYMBAL_ON 0x02 +#define OPL3_HIHAT_ON 0x01 + +/* + * Offsets to the register banks for operators. To get the + * register number just add the operator offset to the bank offset + * + * AM/VIB/EG/KSR/Multiple (0x20 to 0x35) + */ +#define OPL3_AM_VIB 0x20 +#define OPL3_TREMOLO_ON 0x80 +#define OPL3_VIBRATO_ON 0x40 +#define OPL3_SUSTAIN_ON 0x20 +#define OPL3_KSR 0x10 /* Key scaling rate */ +#define OPL3_MULTIPLE_MASK 0x0f /* Frequency multiplier */ + +/* + * KSL/Total level (0x40 to 0x55) + */ +#define OPL3_KSL_LEVEL 0x40 +#define OPL3_KSL_MASK 0xc0 /* Envelope scaling bits */ +#define OPL3_TOTAL_LEVEL_MASK 0x3f /* Strength (volume) of OP */ + +/* + * Attack / Decay rate (0x60 to 0x75) + */ +#define OPL3_ATTACK_DECAY 0x60 +#define OPL3_ATTACK_MASK 0xf0 +#define OPL3_DECAY_MASK 0x0f + +/* + * Sustain level / Release rate (0x80 to 0x95) + */ +#define OPL3_SUSTAIN_RELEASE 0x80 +#define OPL3_SUSTAIN_MASK 0xf0 +#define OPL3_RELEASE_MASK 0x0f + +/* + * Wave select (0xE0 to 0xF5) + */ +#define OPL3_WAVE_SELECT 0xe0 + +/* + * Offsets to the register banks for voices. Just add to the + * voice number to get the register number. + * + * F-Number low bits (0xA0 to 0xA8). + */ +#define OPL3_FNUM_LOW 0xa0 + +/* + * F-number high bits / Key on / Block (octave) (0xB0 to 0xB8) + */ +#define OPL3_KEYON_BLOCK 0xb0 +#define OPL3_KEYON_BIT 0x20 +#define OPL3_BLOCKNUM_MASK 0x1c +#define OPL3_FNUM_HIGH_MASK 0x03 + +/* + * Feedback / Connection (0xc0 to 0xc8) + * + * These registers have two new bits when the OPL-3 mode + * is selected. These bits controls connecting the voice + * to the stereo channels. For 4 OP voices this bit is + * defined in the second half of the voice (add 3 to the + * register offset). + * + * For 4 OP voices the connection bit is used in the + * both halfs (gives 4 ways to connect the operators). + */ +#define OPL3_FEEDBACK_CONNECTION 0xc0 +#define OPL3_FEEDBACK_MASK 0x0e /* Valid just for 1st OP of a voice */ +#define OPL3_CONNECTION_BIT 0x01 +#define OPL3_STEREO_BITS 0x30 /* OPL-3 only */ +#define OPL3_VOICE_TO_LEFT 0x10 +#define OPL3_VOICE_TO_RIGHT 0x20 + +#endif // opl3_reg_h__ diff --git a/source/audiolib/include/sndcards.h b/source/audiolib/include/sndcards.h index bc6acffd7..b272480c7 100644 --- a/source/audiolib/include/sndcards.h +++ b/source/audiolib/include/sndcards.h @@ -33,7 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. typedef enum { - ASS_NoSound, ASS_SDL, ASS_DirectSound, ASS_OPL3, diff --git a/source/audiolib/src/driver_adlib.cpp b/source/audiolib/src/driver_adlib.cpp index 599601ec8..aefb10bc5 100644 --- a/source/audiolib/src/driver_adlib.cpp +++ b/source/audiolib/src/driver_adlib.cpp @@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "midi.h" #include "midifuncs.h" #include "opl3.h" +#include "opl3_reg.h" #include "c_cvars.h" CUSTOM_CVARD(Bool, mus_al_stereo, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enable/disable OPL3 stereo mode") @@ -127,7 +128,7 @@ static opl3_chip chip; opl3_chip *AL_GetChip(void) { return &chip; } -static constexpr uint32_t OctavePitch[MAX_OCTAVE+1] = { +static uint32_t constexpr OctavePitch[MAX_OCTAVE+1] = { OCTAVE_0, OCTAVE_1, OCTAVE_2, OCTAVE_3, OCTAVE_4, OCTAVE_5, OCTAVE_6, OCTAVE_7, }; @@ -141,7 +142,7 @@ static uint32_t NoteDiv12[MAX_NOTE+1]; // { C, C_SHARP, D, D_SHARP, E, F, F_SHARP, G, G_SHARP, A, A_SHARP, B }, // }; -static constexpr uint32_t NotePitch[FINETUNE_MAX+1][12] = { +static uint32_t constexpr NotePitch[FINETUNE_MAX+1][12] = { { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287 }, { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x242, 0x264, 0x288 }, { 0x158, 0x16c, 0x182, 0x199, 0x1b1, 0x1cb, 0x1e6, 0x203, 0x221, 0x243, 0x265, 0x289 }, @@ -179,7 +180,7 @@ static constexpr uint32_t NotePitch[FINETUNE_MAX+1][12] = { // Slot numbers as a function of the voice and the operator. // ( melodic only) -static constexpr int slotVoice[NUMADLIBVOICES][2] = { +static int constexpr slotVoice[NUMADLIBVOICES][2] = { { 0, 3 }, // voice 0 { 1, 4 }, // 1 { 2, 5 }, // 2 @@ -197,7 +198,7 @@ static int VoiceKsl[AL_NumChipSlots][2]; // This table gives the offset of each slot within the chip. // offset = fn( slot) -static constexpr int8_t offsetSlot[AL_NumChipSlots] = { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 }; +static int8_t constexpr offsetSlot[AL_NumChipSlots] = { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 }; static int VoiceReserved[NUMADLIBVOICES * 2]; @@ -206,10 +207,14 @@ static AdLibVoiceList Voice_Pool; static AdLibChannel Channel[NUMADLIBCHANNELS]; -static int AL_LeftPort = ADLIB_PORT; -static int AL_RightPort = ADLIB_PORT; +static int constexpr AL_LeftPort = ADLIB_PORT; +static int constexpr AL_RightPort = ADLIB_PORT + 2; + +static int constexpr AL_MaxMidiChannel = ARRAY_SIZE(Channel); + int AL_Stereo = TRUE; -static int AL_MaxMidiChannel = 16; + +int AL_PostAmp = 3; // TODO: clean up this shit... #define OFFSET(structure, offset) (*((char **)&(structure)[offset])) @@ -260,8 +265,7 @@ static void AL_SendOutputToPort(int const port, int const reg, int const data) static void AL_SendOutput(int const voice, int const reg, int const data) { - int port = (voice == 0) ? AL_RightPort : AL_LeftPort; - AL_SendOutputToPort(port, reg, data); + AL_SendOutputToPort(voice ? AL_LeftPort : AL_RightPort, reg, data); } @@ -282,39 +286,39 @@ static void AL_SetVoiceTimbre(int const voice) int slot = slotVoice[voc][0]; int off = offsetSlot[slot]; - VoiceLevel[slot][port] = 63 - (timbre->Level[0] & 0x3f); - VoiceKsl[slot][port] = timbre->Level[0] & 0xc0; + VoiceLevel[slot][port] = OPL3_TOTAL_LEVEL_MASK - (timbre->Level[0] & OPL3_TOTAL_LEVEL_MASK); + VoiceKsl[slot][port] = timbre->Level[0] & OPL3_KSL_MASK; - AL_SendOutput(port, 0xA0 + voc, 0); - AL_SendOutput(port, 0xB0 + voc, 0); + AL_SendOutput(port, OPL3_FNUM_LOW + voc, 0); + AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, 0); // Let voice clear the release - AL_SendOutput(port, 0x80 + off, 0xff); + AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, 0xff); - AL_SendOutput(port, 0x60 + off, timbre->Env1[0]); - AL_SendOutput(port, 0x80 + off, timbre->Env2[0]); - AL_SendOutput(port, 0x20 + off, timbre->SAVEK[0]); - AL_SendOutput(port, 0xE0 + off, timbre->Wave[0]); + AL_SendOutput(port, OPL3_ATTACK_DECAY + off, timbre->Env1[0]); + AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, timbre->Env2[0]); + AL_SendOutput(port, OPL3_ENABLE_WAVE_SELECT + off, timbre->SAVEK[0]); + AL_SendOutput(port, OPL3_WAVE_SELECT + off, timbre->Wave[0]); - AL_SendOutput(port, 0x40 + off, timbre->Level[0]); + AL_SendOutput(port, OPL3_KSL_LEVEL + off, timbre->Level[0]); slot = slotVoice[voc][1]; - AL_SendOutput(port, 0xC0 + voc, (timbre->Feedback & 0x0f) | 0x30); + AL_SendOutput(port, OPL3_FEEDBACK_CONNECTION + voc, (timbre->Feedback & OPL3_FEEDBACK_MASK) | OPL3_STEREO_BITS); off = offsetSlot[slot]; - VoiceLevel[slot][port] = 63 - (timbre->Level[1] & 0x3f); - VoiceKsl[slot][port] = timbre->Level[1] & 0xc0; + VoiceLevel[slot][port] = OPL3_TOTAL_LEVEL_MASK - (timbre->Level[1] & OPL3_TOTAL_LEVEL_MASK); + VoiceKsl[slot][port] = timbre->Level[1] & OPL3_KSL_MASK; - AL_SendOutput(port, 0x40 + off, 63); + AL_SendOutput(port, OPL3_KSL_LEVEL + off, OPL3_TOTAL_LEVEL_MASK); // Let voice clear the release - AL_SendOutput(port, 0x80 + off, 0xff); + AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, 0xff); - AL_SendOutput(port, 0x60 + off, timbre->Env1[1]); - AL_SendOutput(port, 0x80 + off, timbre->Env2[1]); - AL_SendOutput(port, 0x20 + off, timbre->SAVEK[1]); - AL_SendOutput(port, 0xE0 + off, timbre->Wave[1]); + AL_SendOutput(port, OPL3_ATTACK_DECAY + off, timbre->Env1[1]); + AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, timbre->Env2[1]); + AL_SendOutput(port, OPL3_ENABLE_WAVE_SELECT + off, timbre->SAVEK[1]); + AL_SendOutput(port, OPL3_WAVE_SELECT + off, timbre->Wave[1]); } @@ -332,10 +336,10 @@ static void AL_SetVoiceVolume(int const voice) auto t1 = (uint32_t)VoiceLevel[slot][port] * (velocity + 0x80); t1 = (Channel[channel].Volume * t1) >> 15; - uint32_t volume = t1 ^ 63; + uint32_t volume = t1 ^ OPL3_TOTAL_LEVEL_MASK; volume |= (uint32_t)VoiceKsl[slot][port]; - AL_SendOutput(port, 0x40 + offsetSlot[slot], volume); + AL_SendOutput(port, OPL3_KSL_LEVEL + offsetSlot[slot], volume); // Check if this timbre is Additive if (timbre->Feedback & 0x01) @@ -349,24 +353,22 @@ static void AL_SetVoiceVolume(int const voice) t2 = (Channel[channel].Volume * t1) >> 15; - volume = t2 ^ 63; + volume = t2 ^ OPL3_TOTAL_LEVEL_MASK; volume |= (uint32_t)VoiceKsl[slot][port]; - AL_SendOutput(port, 0x40 + offsetSlot[slot], volume); + AL_SendOutput(port, OPL3_KSL_LEVEL + offsetSlot[slot], volume); } } static int AL_AllocVoice(void) { - if (Voice_Pool.start) - { + if (!Voice_Pool.start) + return AL_VoiceNotFound; + int const voice = Voice_Pool.start->num; LL_Remove(AdLibVoice, &Voice_Pool, &Voice[voice]); return voice; - } - - return AL_VoiceNotFound; } @@ -418,8 +420,8 @@ static void AL_SetVoicePitch(int const voice) pitch |= Voice[voice].status; - AL_SendOutput(port, 0xA0 + voc, pitch); - AL_SendOutput(port, 0xB0 + voc, pitch >> 8); + AL_SendOutput(port, OPL3_FNUM_LOW + voc, pitch); + AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, pitch >> 8); } static void AL_SetVoicePan(int const voice) @@ -531,32 +533,32 @@ static void AL_FlushCard(int const port) auto slot1 = offsetSlot[slotVoice[i][0]]; auto slot2 = offsetSlot[slotVoice[i][1]]; - AL_SendOutputToPort(port, 0xA0 + i, 0); - AL_SendOutputToPort(port, 0xB0 + i, 0); + AL_SendOutputToPort(port, OPL3_FNUM_LOW + i, 0); + AL_SendOutputToPort(port, OPL3_KEYON_BLOCK + i, 0); - AL_SendOutputToPort(port, 0xE0 + slot1, 0); - AL_SendOutputToPort(port, 0xE0 + slot2, 0); + AL_SendOutputToPort(port, OPL3_WAVE_SELECT + slot1, 0); + AL_SendOutputToPort(port, OPL3_WAVE_SELECT + slot2, 0); // Set the envelope to be fast and quiet - AL_SendOutputToPort(port, 0x60 + slot1, 0xff); - AL_SendOutputToPort(port, 0x60 + slot2, 0xff); - AL_SendOutputToPort(port, 0x80 + slot1, 0xff); - AL_SendOutputToPort(port, 0x80 + slot2, 0xff); + AL_SendOutputToPort(port, OPL3_ATTACK_DECAY + slot1, 0xff); + AL_SendOutputToPort(port, OPL3_ATTACK_DECAY + slot2, 0xff); + AL_SendOutputToPort(port, OPL3_SUSTAIN_RELEASE + slot1, 0xff); + AL_SendOutputToPort(port, OPL3_SUSTAIN_RELEASE + slot2, 0xff); // Maximum attenuation - AL_SendOutputToPort(port, 0x40 + slot1, 0xff); - AL_SendOutputToPort(port, 0x40 + slot2, 0xff); + AL_SendOutputToPort(port, OPL3_KSL_LEVEL + slot1, 0xff); + AL_SendOutputToPort(port, OPL3_KSL_LEVEL + slot2, 0xff); } } static void AL_Reset(void) { - AL_SendOutputToPort(ADLIB_PORT, 1, 0x20); - AL_SendOutputToPort(ADLIB_PORT, 0x08, 0); + AL_SendOutputToPort(ADLIB_PORT, 1, OPL3_ENABLE_WAVE_SELECT); + AL_SendOutputToPort(ADLIB_PORT, OPL3_KBD_SPLIT_REGISTER, 0); // Set the values: AM Depth, VIB depth & Rhythm - AL_SendOutputToPort(ADLIB_PORT, 0xBD, 0); + AL_SendOutputToPort(ADLIB_PORT, OPL3_PERCUSSION_REGISTER, 0); AL_SetStereo(AL_Stereo); @@ -565,10 +567,7 @@ static void AL_Reset(void) } -void AL_SetStereo(int const stereo) -{ - AL_SendOutputToPort(AL_RightPort, 0x5, (stereo<<1)+1); -} +void AL_SetStereo(int const stereo) { AL_SendOutputToPort(AL_RightPort, OPL3_MODE_REGISTER, (stereo << 1) + 1); } static void AL_NoteOff(int const channel, int const key, int velocity) @@ -579,17 +578,17 @@ static void AL_NoteOff(int const channel, int const key, int velocity) if (channel > AL_MaxMidiChannel) return; - int voice = AL_GetVoice(channel, key); + int const voice = AL_GetVoice(channel, key); if (voice == AL_VoiceNotFound) return; Voice[voice].status = NOTE_OFF; - int port = Voice[voice].port; - int voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; + int const port = Voice[voice].port; + int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; - AL_SendOutput(port, 0xB0 + voc, hibyte(Voice[voice].pitchleft)); + AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, hibyte(Voice[voice].pitchleft)); LL_Remove(AdLibVoice, &Channel[channel].Voices, &Voice[voice]); LL_AddToTail(AdLibVoice, &Voice_Pool, &Voice[voice]); @@ -720,12 +719,9 @@ static void AL_SetPitchBend(int const channel, int const lsb, int const msb) return; int const pitchbend = lsb + (msb << 8); + int const TotalBend = pitchbend * Channel[channel].PitchBendRange / (PITCHBEND_CENTER / FINETUNE_RANGE); Channel[channel].Pitchbend = pitchbend; - - int TotalBend = pitchbend * Channel[channel].PitchBendRange; - TotalBend /= (PITCHBEND_CENTER / FINETUNE_RANGE); - Channel[channel].KeyOffset = (int)(TotalBend / FINETUNE_RANGE); Channel[channel].KeyOffset -= Channel[channel].PitchBendSemiTones; @@ -751,9 +747,6 @@ static int AL_Init(int const rate) { OPL3_Reset(&chip, rate); - AL_LeftPort = ADLIB_PORT; - AL_RightPort = ADLIB_PORT + 2; - AL_CalcPitchInfo(); AL_Reset(); AL_ResetVoices(); @@ -762,7 +755,7 @@ static int AL_Init(int const rate) } -void AL_RegisterTimbreBank(uint8_t *timbres) +void AL_RegisterTimbreBank(uint8_t const *timbres) { for (int i = 0; i < 256; i++) { diff --git a/source/audiolib/src/driver_adlib.h b/source/audiolib/src/driver_adlib.h index 1ddd90544..198d84ae8 100644 --- a/source/audiolib/src/driver_adlib.h +++ b/source/audiolib/src/driver_adlib.h @@ -23,6 +23,7 @@ #include "opl3.h" extern int AL_Stereo; +extern int AL_PostAmp; int AdLibDrv_GetError(void); const char *AdLibDrv_ErrorString(int ErrorNumber); diff --git a/source/audiolib/src/driver_nosound.cpp b/source/audiolib/src/driver_nosound.cpp deleted file mode 100644 index fc7a786e8..000000000 --- a/source/audiolib/src/driver_nosound.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - 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 the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - -/** - * Stub driver for no output - */ - -#include "compat.h" -#include "midifuncs.h" - -int NoSoundDrv_GetError(void) { return 0; } - -const char *NoSoundDrv_ErrorString(int ErrorNumber) -{ - UNREFERENCED_PARAMETER(ErrorNumber); - return "No sound, Ok."; -} - -int NoSoundDrv_PCM_Init(int *mixrate, int *numchannels, void *initdata) -{ - UNREFERENCED_PARAMETER(mixrate); - UNREFERENCED_PARAMETER(numchannels); - UNREFERENCED_PARAMETER(initdata); - return 0; -} - -void NoSoundDrv_PCM_Shutdown(void) {} - -int NoSoundDrv_PCM_BeginPlayback(char *BufferStart, int BufferSize, int NumDivisions, void (*CallBackFunc)(void)) -{ - UNREFERENCED_PARAMETER(BufferStart); - UNREFERENCED_PARAMETER(BufferSize); - UNREFERENCED_PARAMETER(NumDivisions); - UNREFERENCED_PARAMETER(CallBackFunc); - return 0; -} - -void NoSoundDrv_PCM_StopPlayback(void) {} -void NoSoundDrv_PCM_Lock(void) {} -void NoSoundDrv_PCM_Unlock(void) {} - -int NoSoundDrv_MIDI_Init(midifuncs *funcs) -{ - Bmemset(funcs, 0, sizeof(midifuncs)); - return 0; -} - -void NoSoundDrv_MIDI_Shutdown(void) {} - -int NoSoundDrv_MIDI_StartPlayback(void (*service)(void)) -{ - UNREFERENCED_PARAMETER(service); - return 0; -} - -void NoSoundDrv_MIDI_HaltPlayback(void) {} -uint32_t NoSoundDrv_MIDI_GetTick(void) { return 0; } - -void NoSoundDrv_MIDI_SetTempo(int tempo, int division) -{ - UNREFERENCED_PARAMETER(tempo); - UNREFERENCED_PARAMETER(division); -} - -void NoSoundDrv_MIDI_Lock(void) {} -void NoSoundDrv_MIDI_Unlock(void) {} diff --git a/source/audiolib/src/driver_nosound.h b/source/audiolib/src/driver_nosound.h deleted file mode 100644 index 9d0f7496b..000000000 --- a/source/audiolib/src/driver_nosound.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - 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 the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -#include "midifuncs.h" - -#include - -int NoSoundDrv_GetError(void); -const char *NoSoundDrv_ErrorString( int ErrorNumber ); - -int NoSoundDrv_PCM_Init(int * mixrate, int * numchannels, void * initdata); -void NoSoundDrv_PCM_Shutdown(void); -int NoSoundDrv_PCM_BeginPlayback(char *BufferStart, int BufferSize, - int NumDivisions, void ( *CallBackFunc )( void ) ); -void NoSoundDrv_PCM_StopPlayback(void); -void NoSoundDrv_PCM_Lock(void); -void NoSoundDrv_PCM_Unlock(void); - -int NoSoundDrv_MIDI_Init(midifuncs *); -void NoSoundDrv_MIDI_Shutdown(void); -int NoSoundDrv_MIDI_StartPlayback(void (*service)(void)); -void NoSoundDrv_MIDI_HaltPlayback(void); -uint32_t NoSoundDrv_MIDI_GetTick(void); -void NoSoundDrv_MIDI_SetTempo(int tempo, int division); -void NoSoundDrv_MIDI_Lock(void); -void NoSoundDrv_MIDI_Unlock(void); \ No newline at end of file diff --git a/source/audiolib/src/drivers.cpp b/source/audiolib/src/drivers.cpp index d33da4c5c..57d90f12b 100644 --- a/source/audiolib/src/drivers.cpp +++ b/source/audiolib/src/drivers.cpp @@ -25,7 +25,6 @@ #include "drivers.h" -#include "driver_nosound.h" #include "driver_adlib.h" #ifdef RENDERTYPESDL @@ -67,26 +66,7 @@ static struct { void (*MIDI_Unlock)(void); } SoundDrivers[ASS_NumSoundCards] = { - // Everyone gets the "no sound" driver - { - "null sound device", - NoSoundDrv_GetError, - NoSoundDrv_ErrorString, - NoSoundDrv_PCM_Init, - NoSoundDrv_PCM_Shutdown, - NoSoundDrv_PCM_BeginPlayback, - NoSoundDrv_PCM_StopPlayback, - NoSoundDrv_PCM_Lock, - NoSoundDrv_PCM_Unlock, - NoSoundDrv_MIDI_Init, - NoSoundDrv_MIDI_Shutdown, - NoSoundDrv_MIDI_StartPlayback, - NoSoundDrv_MIDI_HaltPlayback, - NoSoundDrv_MIDI_SetTempo, - NoSoundDrv_MIDI_Lock, - NoSoundDrv_MIDI_Unlock, - }, - + // Simple DirectMedia Layer { "SDL", diff --git a/source/audiolib/src/fx_man.cpp b/source/audiolib/src/fx_man.cpp index 9d0d702e7..d9ad4cc18 100644 --- a/source/audiolib/src/fx_man.cpp +++ b/source/audiolib/src/fx_man.cpp @@ -62,8 +62,6 @@ int FX_Init(int numvoices, int numchannels, int mixrate, void *initdata) SoundCard = ASS_SDL; #elif defined RENDERTYPEWIN SoundCard = ASS_DirectSound; -#else - SoundCard = ASS_NoSound; #endif } @@ -76,8 +74,8 @@ int FX_Init(int numvoices, int numchannels, int mixrate, void *initdata) if (SoundDriver_IsPCMSupported(SoundCard) == 0) { // unsupported cards fall back to no sound - MV_Printf("Couldn't init %s, falling back to no sound...\n", SoundDriver_GetName(SoundCard)); - SoundCard = ASS_NoSound; + FX_SetErrorCode(FX_InvalidCard); + return FX_Error; } int status = FX_Ok; diff --git a/source/audiolib/src/midi.cpp b/source/audiolib/src/midi.cpp index 5347c74e4..cef907974 100644 --- a/source/audiolib/src/midi.cpp +++ b/source/audiolib/src/midi.cpp @@ -538,8 +538,8 @@ static void _MIDI_ServiceMultivoc(void) } if (MV_MIDIRenderTempo >= 0) MV_MIDIRenderTimer += MV_MIDIRenderTempo; OPL3_GenerateResampled(AL_GetChip(), buf); - *buffer16++ = clamp(buf[0]<<3, INT16_MIN, INT16_MAX); - *buffer16++ = clamp(buf[1]<<3, INT16_MIN, INT16_MAX); + *buffer16++ = clamp(buf[0]<statnum) { @@ -4211,7 +4211,7 @@ void ProcessTouchObjects(spritetype *pSprite, int nXSprite) if (pSprite2->statnum == kStatThing) { int nType = pSprite2->type-kThingBase; - THINGINFO *pThingInfo = &thingInfo[nType]; + const THINGINFO *pThingInfo = &thingInfo[nType]; if (pThingInfo->flags&1) pSprite2->flags |= 1; @@ -4546,7 +4546,7 @@ int MoveThing(spritetype *pSprite) int nSprite = pSprite->index; int v8 = 0; dassert(pSprite->type >= kThingBase && pSprite->type < kThingMax); - THINGINFO *pThingInfo = &thingInfo[pSprite->type-kThingBase]; + const THINGINFO *pThingInfo = &thingInfo[pSprite->type-kThingBase]; int nSector = pSprite->sectnum; dassert(nSector >= 0 && nSector < kMaxSectors); int top, bottom; @@ -5829,7 +5829,7 @@ void actProcessSprites(void) if (pXSector && pXSector->panVel && (pXSector->panAlways || pXSector->state || pXSector->busy)) { int nType = pSprite->type - kThingBase; - THINGINFO *pThingInfo = &thingInfo[nType]; + const THINGINFO *pThingInfo = &thingInfo[nType]; if (pThingInfo->flags & 1) pSprite->flags |= 1; @@ -6546,7 +6546,7 @@ spritetype * actSpawnThing(int nSector, int x, int y, int z, int nThingType) pSprite->type = nThingType; dassert(nXThing > 0 && nXThing < kMaxXSprites); XSPRITE *pXThing = &xsprite[nXThing]; - THINGINFO *pThingInfo = &thingInfo[nType]; + const THINGINFO *pThingInfo = &thingInfo[nType]; pXThing->health = pThingInfo->startHealth<<4; pSprite->clipdist = pThingInfo->clipdist; pSprite->flags = pThingInfo->flags; diff --git a/source/blood/src/actor.h b/source/blood/src/actor.h index 42b785ca8..6d7e8de6d 100644 --- a/source/blood/src/actor.h +++ b/source/blood/src/actor.h @@ -186,7 +186,7 @@ extern WEAPONITEMDATA gWeaponItemData[]; extern ITEMDATA gItemData[]; extern MissileType missileInfo[]; extern EXPLOSION explodeInfo[]; -extern THINGINFO thingInfo[]; +extern const THINGINFO thingInfo[]; extern VECTORDATA gVectorData[]; extern int gDudeDrag; diff --git a/source/blood/src/aiunicult.cpp b/source/blood/src/aiunicult.cpp index 73e726a2b..c81d69b17 100644 --- a/source/blood/src/aiunicult.cpp +++ b/source/blood/src/aiunicult.cpp @@ -284,7 +284,7 @@ static void ThrowThing(int nXIndex, bool impact) { if (curWeapon < kThingBase || curWeapon >= kThingMax) return; - THINGINFO* pThinkInfo = &thingInfo[curWeapon - kThingBase]; + const THINGINFO* pThinkInfo = &thingInfo[curWeapon - kThingBase]; if (!pThinkInfo->allowThrow) return; if (!playGenDudeSound(pSprite, kGenDudeSndAttackThrow)) diff --git a/source/blood/src/barf.cpp b/source/blood/src/barf.cpp index 839f59766..84cfbd697 100644 --- a/source/blood/src/barf.cpp +++ b/source/blood/src/barf.cpp @@ -166,7 +166,7 @@ int RFS::Open(const char *fileName) { strcpy(_fileName, fileName); - auto hFile = kopenFileReader(fileName, 0); + auto hFile = fileSystem.OpenFileReader(fileName, 0); if (!hFile.isOpen()) { initprintf("BARF: Error opening file %s", _fileName); return 1; diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index e97287208..2bb26e7c9 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -48,7 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "globals.h" #include "levels.h" #include "loadsave.h" -#include "menu.h" +#include "gamemenu.h" #include "mirrors.h" #include "music.h" #include "network.h" @@ -71,6 +71,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gamecontrol.h" #include "m_argv.h" #include "statistics.h" +#include "menu/menu.h" #ifdef _WIN32 # include @@ -97,8 +98,6 @@ char bAddUserMap = false; bool bNoDemo = false; bool bQuickStart = true; -int gMusicPrevLoadedEpisode = -1; -int gMusicPrevLoadedLevel = -1; char gUserMapFilename[BMAX_PATH]; @@ -376,7 +375,7 @@ static void PrecacheSounds(void) if (pNode->ResType() == NAME_RAW || pNode->ResType() == NAME_SFX) { pNode->Get(); - if ((i&15) == 15) gameHandleEvents(); // don't do this too often. That made sense in 1996 but not in 2019 + //if ((i&15) == 15) gameHandleEvents(); // don't do this too often. That made sense in 1996 but not in 2019 } } } @@ -387,8 +386,6 @@ void PreloadCache(void) if (gDemo.at1) return; PrecacheSounds(); - if (mus_restartonload) - sndTryPlaySpecialMusic(MUS_LOADING); PreloadTiles(); ClockTicks clock = totalclock; int cnt = 0; @@ -485,8 +482,6 @@ void StartLevel(GAMEOPTIONS *gameOptions) EndLevel(); gStartNewGame = 0; ready2send = 0; - gMusicPrevLoadedEpisode = gGameOptions.nEpisode; - gMusicPrevLoadedLevel = gGameOptions.nLevel; if (gDemo.at0 && gGameStarted) gDemo.Close(); netWaitForEveryone(0); @@ -547,6 +542,7 @@ void StartLevel(GAMEOPTIONS *gameOptions) return; } char levelName[BMAX_PATH]; + currentLevel = &mapList[gGameOptions.nEpisode * kMaxLevels + gGameOptions.nLevel]; STAT_NewLevel(gameOptions->zLevelName); G_LoadMapHack(levelName, gameOptions->zLevelName); wsrand(gameOptions->uMapCRC); @@ -719,8 +715,8 @@ void StartLevel(GAMEOPTIONS *gameOptions) gCacheMiss = 0; gFrame = 0; gChokeCounter = 0; - if (!gDemo.at1) - gGameMenuMgr.Deactivate(); + if (!gDemo.at1) + M_ClearMenus(); levelTryPlayMusicOrNothing(gGameOptions.nEpisode, gGameOptions.nLevel); // viewSetMessage(""); viewSetErrorMessage(""); @@ -768,38 +764,6 @@ void StartNetworkLevel(void) int gDoQuickSave = 0; -static void DoQuickLoad(void) -{ - if (!gGameMenuMgr.m_bActive) - { - if (gQuickLoadSlot != -1) - { - QuickLoadGame(); - return; - } - if (gQuickLoadSlot == -1 && gQuickSaveSlot != -1) - { - gQuickLoadSlot = gQuickSaveSlot; - QuickLoadGame(); - return; - } - gGameMenuMgr.Push(&menuLoadGame,-1); - } -} - -static void DoQuickSave(void) -{ - if (gGameStarted && !gGameMenuMgr.m_bActive && gPlayer[myconnectindex].pXSprite->health != 0) - { - if (gQuickSaveSlot != -1) - { - QuickSaveGame(); - return; - } - gGameMenuMgr.Push(&menuSaveGame,-1); - } -} - void LocalKeys(void) { bool alt = inputState.AltPressed(); @@ -837,21 +801,6 @@ void LocalKeys(void) gView = &gPlayer[gViewIndex]; } } - if (gDoQuickSave) - { - inputState.keyFlushScans(); - switch (gDoQuickSave) - { - case 1: - DoQuickSave(); - break; - case 2: - DoQuickLoad(); - break; - } - gDoQuickSave = 0; - return; - } char key; if ((key = inputState.keyGetScan()) != 0) { @@ -872,78 +821,21 @@ void LocalKeys(void) buttonMap.ClearButton(gamefunc_See_Chase_View); return; } +#if 0 switch (key) { case sc_kpad_Period: case sc_Delete: if (ctrl && alt) { - gQuitGame = 1; + gQuitGame = 1; // uh, what? return; } break; - case sc_Escape: - inputState.keyFlushScans(); - if (gGameStarted && gPlayer[myconnectindex].pXSprite->health != 0) - { - if (!gGameMenuMgr.m_bActive) - gGameMenuMgr.Push(&menuMainWithSave,-1); - } - else - { - if (!gGameMenuMgr.m_bActive) - gGameMenuMgr.Push(&menuMain,-1); - } - return; - case sc_F1: - inputState.keyFlushScans(); - if (gGameOptions.nGameType == 0) - gGameMenuMgr.Push(&menuOrder,-1); - break; - case sc_F2: - inputState.keyFlushScans(); - if (!gGameMenuMgr.m_bActive && gGameOptions.nGameType == 0) - gGameMenuMgr.Push(&menuSaveGame,-1); - break; - case sc_F3: - inputState.keyFlushScans(); - if (!gGameMenuMgr.m_bActive && gGameOptions.nGameType == 0) - gGameMenuMgr.Push(&menuLoadGame,-1); - break; - case sc_F4: - inputState.keyFlushScans(); - if (!gGameMenuMgr.m_bActive) - gGameMenuMgr.Push(&menuOptionsSound,-1); - return; - case sc_F5: - inputState.keyFlushScans(); - if (!gGameMenuMgr.m_bActive) - gGameMenuMgr.Push(&menuOptions,-1); - return; - case sc_F6: - inputState.keyFlushScans(); - DoQuickSave(); - break; - case sc_F8: - inputState.keyFlushScans(); - if (!gGameMenuMgr.m_bActive) - gGameMenuMgr.Push(&menuOptionsDisplayMode, -1); - return; - case sc_F9: - inputState.keyFlushScans(); - DoQuickLoad(); - break; - case sc_F10: - inputState.keyFlushScans(); - if (!gGameMenuMgr.m_bActive) - gGameMenuMgr.Push(&menuQuit,-1); - break; - case sc_F11: - break; - case sc_F12: - videoCaptureScreen(); + case default: break; } +#endif } } @@ -1007,7 +899,7 @@ void ProcessFrame(void) viewClearInterpolations(); if (!gDemo.at1) { - if (gPaused || gEndGameMgr.at0 || (gGameOptions.nGameType == 0 && gGameMenuMgr.m_bActive)) + if (gPaused || gEndGameMgr.at0 || (gGameOptions.nGameType == 0 && M_Active())) return; if (gDemo.at0) gDemo.Write(gFifoInput[(gNetFifoTail-1)&255]); @@ -1056,7 +948,7 @@ void ProcessFrame(void) } if (gDemo.at0) gDemo.Close(); - sndFadeSong(4000); + Mus_Fade(4000); seqKillAll(); if (gGameOptions.uGameFlags&2) { @@ -1064,8 +956,9 @@ void ProcessFrame(void) { if (gGameOptions.uGameFlags&8) levelPlayEndScene(gGameOptions.nEpisode); - gGameMenuMgr.Deactivate(); - gGameMenuMgr.Push(&menuCredits,-1); + + M_StartControlPanel(false); + M_SetMenu(NAME_CreditsMenu); } gGameOptions.uGameFlags &= ~3; gRestartGame = 1; @@ -1313,7 +1206,6 @@ int GameInterface::app_main() levelAddUserMap(gUserMapFilename); gStartNewGame = 1; } - SetupMenus(); videoSetViewableArea(0, 0, xdim - 1, ydim - 1); if (!bQuickStart) credLogosDos(); @@ -1349,26 +1241,21 @@ RESTART: else if (gDemo.at1 && !bAddUserMap && !bNoDemo) gDemo.Playback(); if (gDemo.at59ef > 0) - gGameMenuMgr.Deactivate(); - if (!bAddUserMap && !gGameStarted) - gGameMenuMgr.Push(&menuMain, -1); + M_ClearMenus(); + if (!bAddUserMap && !gGameStarted) + { + M_StartControlPanel(false); + M_SetMenu(NAME_MainMenu); + } ready2send = 1; while (!gQuitGame) { - if (handleevents() && quitevent) - { - inputState.SetKeyStatus(sc_Escape, 1); - quitevent = 0; - } + handleevents(); netUpdate(); MUSIC_Update(); inputState.SetBindsEnabled(gInputMode == kInputGame); switch (gInputMode) { - case kInputMenu: - if (gGameMenuMgr.m_bActive) - gGameMenuMgr.Process(); - break; case kInputGame: LocalKeys(); break; @@ -1445,10 +1332,6 @@ RESTART: { switch (gInputMode) { - case kInputMenu: - if (gGameMenuMgr.m_bActive) - gGameMenuMgr.Draw(); - break; case kInputMessage: gPlayerMsg.ProcessKeys(); gPlayerMsg.Draw(); @@ -1475,7 +1358,6 @@ RESTART: //} if (gStartNewGame) { - STAT_StartNewGame(gEpisodeInfo[gGameOptions.nEpisode].at0, gGameOptions.nDifficulty); StartLevel(&gGameOptions); } } @@ -1485,13 +1367,15 @@ RESTART: if (gRestartGame) { UpdateDacs(0, true); - sndStopSong(); + Mus_Stop(); FX_StopAllSounds(); gQuitGame = 0; gQuitRequest = 0; gRestartGame = 0; gGameStarted = 0; levelSetupOptions(0,0); +#if 0 + // What's this loop for? Needs checking while (gGameMenuMgr.m_bActive) { gGameMenuMgr.Process(); @@ -1503,6 +1387,7 @@ RESTART: videoNextPage(); } } +#endif if (gGameOptions.nGameType != 0) { if (!gDemo.at0 && gDemo.at59ef > 0 && gGameOptions.nGameType == 0 && !bNoDemo) @@ -1560,9 +1445,8 @@ static int32_t S_DefineMusic(const char *ID, const char *name) return -1; } - int nEpisode = sel/kMaxLevels; - int nLevel = sel%kMaxLevels; - return S_DefineAudioIfSupported(gEpisodeInfo[nEpisode].at28[nLevel].atd0, name); + quoteMgr.InitializeQuote(sel, name); + return 0; } static int parsedefinitions_game(scriptfile *, int); @@ -1800,7 +1684,7 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) break; } - if (fileName == NULL || check_file_exist(fileName)) + if (fileName == NULL || fileSystem.FileExists(fileName)) break; if (S_DefineMusic(musicID, fileName) == -1) @@ -2052,7 +1936,7 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) break; } - if (fileName == NULL || check_file_exist(fileName)) + if (fileName == NULL || fileSystem.FileExists(fileName)) break; // maybe I should have just packed this into a sound_t and passed a reference... @@ -2104,29 +1988,18 @@ bool fileExistsRFF(int id, const char *ext) { int sndTryPlaySpecialMusic(int nMusic) { - int nEpisode = nMusic/kMaxLevels; - int nLevel = nMusic%kMaxLevels; - if (sndPlaySong(gEpisodeInfo[nEpisode].at28[nLevel].at0, gEpisodeInfo[nEpisode].at28[nLevel].atd0, true)) + if (Mus_Play(nullptr, quoteMgr.GetQuote(nMusic), true)) { - strncpy(gGameOptions.zLevelSong, gEpisodeInfo[nEpisode].at28[nLevel].atd0, BMAX_PATH); return 0; } - else - { - // Unable to stat the music. - *gGameOptions.zLevelSong = 0; - } return 1; } void sndPlaySpecialMusicOrNothing(int nMusic) { - int nEpisode = nMusic/kMaxLevels; - int nLevel = nMusic%kMaxLevels; if (sndTryPlaySpecialMusic(nMusic)) { - sndStopSong(); - strncpy(gGameOptions.zLevelSong, gEpisodeInfo[nEpisode].at28[nLevel].atd0, BMAX_PATH); + Mus_Stop(); } } diff --git a/source/blood/src/blood.h b/source/blood/src/blood.h index 166f05f61..164d56413 100644 --- a/source/blood/src/blood.h +++ b/source/blood/src/blood.h @@ -46,7 +46,6 @@ extern INICHAIN *pINIChain; enum INPUT_MODE { kInputGame = 0, - kInputMenu, kInputMessage, kInputEndGame, }; @@ -60,8 +59,6 @@ extern bool gRestartGame; extern double g_gameUpdateTime, g_gameUpdateAndDrawTime; extern double g_gameUpdateAvgTime; extern int blood_globalflags; -extern int gMusicPrevLoadedEpisode; -extern int gMusicPrevLoadedLevel; extern int gSaveGameNum; extern bool gPaused; @@ -90,8 +87,21 @@ struct GameInterface : ::GameInterface bool validate_hud(int) override; void set_hud_layout(int size) override; void set_hud_scale(int size) override; - bool mouseInactiveConditional(bool condition) override; FString statFPS() override; + FSavegameInfo GetSaveSig() override; + void MenuOpened() override; + void MenuClosed() override; + bool CanSave() override; + void StartGame(FGameStartup& gs) override; + void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override; + void DrawMenuCaption(const DVector2& origin, const char* text) override; + bool SaveGame(FSaveGameNode*) override; + bool LoadGame(FSaveGameNode*) override; + void DoPrintMessage(int prio, const char*) override; + void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg); + void QuitToTitle() override; + + GameStats getStats() override; }; END_BLD_NS diff --git a/source/blood/src/config.cpp b/source/blood/src/config.cpp index 32fb9e2bb..d0e9b7b45 100644 --- a/source/blood/src/config.cpp +++ b/source/blood/src/config.cpp @@ -50,7 +50,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -int32_t mus_restartonload; int32_t gTurnSpeed; int32_t gDetail; int32_t cl_weaponswitch; diff --git a/source/blood/src/controls.cpp b/source/blood/src/controls.cpp index 3678eaa7c..4a85b6afe 100644 --- a/source/blood/src/controls.cpp +++ b/source/blood/src/controls.cpp @@ -121,60 +121,15 @@ void ctrlGetInput(void) D_ProcessEvents(); - if (in_aimmode) - g_MyAimMode = 0; - - if (buttonMap.ButtonDown(gamefunc_Mouse_Aiming)) - { - if (in_aimmode) - g_MyAimMode = 1; - else - { - buttonMap.ClearButton(gamefunc_Mouse_Aiming); - g_MyAimMode = !g_MyAimMode; - if (g_MyAimMode) - { - if (!bSilentAim) - viewSetMessage("Mouse aiming ON"); - } - else - { - if (!bSilentAim) - viewSetMessage("Mouse aiming OFF"); - gInput.keyFlags.lookCenter = 1; - } - } - } - else if (in_aimmode) - gInput.keyFlags.lookCenter = 1; + bool mouseaim = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); + if (!mouseaim) gInput.keyFlags.lookCenter = 1; CONTROL_GetInput(&info); - if (in_mousedeadzone) - { - if (info.mousey > 0) - info.mousey = max(info.mousey - in_mousedeadzone, 0); - else if (info.mousey < 0) - info.mousey = min(info.mousey + in_mousedeadzone, 0); - - if (info.mousex > 0) - info.mousex = max(info.mousex - in_mousedeadzone, 0); - else if (info.mousex < 0) - info.mousex = min(info.mousex + in_mousedeadzone, 0); - } - - if (in_mousebias) - { - if (klabs(info.mousex) > klabs(info.mousey)) - info.mousey = tabledivide32_noinline(info.mousey, in_mousebias); - else - info.mousex = tabledivide32_noinline(info.mousex, in_mousebias); - } - if (gQuitRequest) gInput.keyFlags.quit = 1; - if (gGameStarted && gInputMode != kInputMessage && gInputMode != kInputMenu + if (gGameStarted && gInputMode != kInputMessage && buttonMap.ButtonDown(gamefunc_SendMessage)) { buttonMap.ClearButton(gamefunc_SendMessage); @@ -182,16 +137,6 @@ void ctrlGetInput(void) gInputMode = kInputMessage; } - if (buttonMap.ButtonDown(gamefunc_AutoRun)) - { - buttonMap.ClearButton(gamefunc_AutoRun); - gAutoRun = !gAutoRun; - if (gAutoRun) - viewSetMessage("Auto run ON"); - else - viewSetMessage("Auto run OFF"); - } - if (buttonMap.ButtonDown(gamefunc_Map_Toggle)) { buttonMap.ClearButton(gamefunc_Map_Toggle); @@ -415,13 +360,7 @@ void ctrlGetInput(void) strafe = ClipRange(strafe-(info.dx<<5), -2048, 2048); -#if 0 - if (info.dz < 0) - gInput.mlook = ClipRange((info.dz+127)>>7, -127, 127); - else - gInput.mlook = ClipRange(info.dz>>7, -127, 127); -#endif - if (g_MyAimMode) + if (mouseaim) gInput.q16mlook = fix16_clamp(fix16_div(fix16_from_int(info.mousey), F16(128)), F16(-127)>>2, F16(127)>>2); else forward = ClipRange(forward - info.mousey, -2048, 2048); diff --git a/source/blood/src/credits.cpp b/source/blood/src/credits.cpp index bc579f1ce..45c2157a2 100644 --- a/source/blood/src/credits.cpp +++ b/source/blood/src/credits.cpp @@ -140,7 +140,7 @@ void credLogosDos(void) rotatesprite(160<<16, 100<<16, 65536, 0, 2518, 0, 0, 0x4a, 0, 0, xdim-1, ydim-1); scrNextPage(); Wait(360); - sndFadeSong(4000); + Mus_Fade(4000); } void credReset(void) @@ -160,14 +160,14 @@ FileReader credKOpen4Load(char *&pzFile) if (pzFile[i] == '\\') pzFile[i] = '/'; } - auto nHandle = kopenFileReader(pzFile, 0); + auto nHandle = fileSystem.OpenFileReader(pzFile, 0); if (!nHandle.isOpen()) { // Hack if (nLen >= 3 && isalpha(pzFile[0]) && pzFile[1] == ':' && pzFile[2] == '/') { pzFile += 3; - nHandle = kopenFileReader(pzFile, 0); + nHandle = fileSystem.OpenFileReader(pzFile, 0); } } return nHandle; diff --git a/source/blood/src/d_menu.cpp b/source/blood/src/d_menu.cpp new file mode 100644 index 000000000..2b81b6317 --- /dev/null +++ b/source/blood/src/d_menu.cpp @@ -0,0 +1,330 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2010-2019 EDuke32 developers and contributors +Copyright (C) 2019 Nuke.YKT + +This file is part of NBlood. + +NBlood is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- + +#include "ns.h" // Must come before everything else! + +#include "build.h" +#include "compat.h" +#include "mouse.h" +#include "common_game.h" +#include "blood.h" +#include "config.h" +#include "gamemenu.h" +#include "globals.h" +#include "inifile.h" +#include "levels.h" +#include "qav.h" +#include "resource.h" +#include "view.h" +#include "demo.h" +#include "network.h" +#include "mmulti.h" +#include "c_bind.h" +#include "menu/menu.h" + +bool ShowOptionMenu(); + +BEGIN_BLD_NS + +class CGameMenuItemQAV +{ +public: + int m_nX, m_nY; + TArray raw; + int at2c; + int lastTick; + bool bWideScreen; + bool bClearBackground; + CGameMenuItemQAV(int, int, const char*, bool widescreen = false, bool clearbackground = false); + void Draw(void); +}; + +CGameMenuItemQAV::CGameMenuItemQAV(int a3, int a4, const char* name, bool widescreen, bool clearbackground) +{ + m_nY = a4; + m_nX = a3; + bWideScreen = widescreen; + bClearBackground = clearbackground; + + if (name) + { + // NBlood read this directly from the file system cache, but let's better store the data locally for robustness. + raw = fileSystem.LoadFile(name, 0); + if (raw.Size() != 0) + { + auto data = (QAV*)raw.Data(); + data->nSprite = -1; + data->x = m_nX; + data->y = m_nY; + data->Preload(); + at2c = data->at10; + lastTick = (int)totalclock; + } + } +} + +void CGameMenuItemQAV::Draw(void) +{ + if (bClearBackground) + videoClearScreen(0); + + if (raw.Size() > 0) + { + auto data = (QAV*)raw.Data(); + ClockTicks backFC = gFrameClock; + gFrameClock = totalclock; + int nTicks = (int)totalclock - lastTick; + lastTick = (int)totalclock; + at2c -= nTicks; + if (at2c <= 0 || at2c > data->at10) + { + at2c = data->at10; + } + data->Play(data->at10 - at2c - nTicks, data->at10 - at2c, -1, NULL); + int wx1, wy1, wx2, wy2; + wx1 = windowxy1.x; + wy1 = windowxy1.y; + wx2 = windowxy2.x; + wy2 = windowxy2.y; + windowxy1.x = 0; + windowxy1.y = 0; + windowxy2.x = xdim - 1; + windowxy2.y = ydim - 1; + if (bWideScreen) + { + int xdim43 = scale(ydim, 4, 3); + int nCount = (xdim + xdim43 - 1) / xdim43; + int backX = data->x; + for (int i = 0; i < nCount; i++) + { + data->Draw(data->at10 - at2c, 10 + kQavOrientationLeft, 0, 0); + data->x += 320; + } + data->x = backX; + } + else + data->Draw(data->at10 - at2c, 10, 0, 0); + + windowxy1.x = wx1; + windowxy1.y = wy1; + windowxy2.x = wx2; + windowxy2.y = wy2; + gFrameClock = backFC; + } +} + + + +static std::unique_ptr itemBloodQAV; // This must be global to ensure that the animation remains consistent across menus. + + +void UpdateNetworkMenus(void) +{ + // For now disable the network menu item as it is not yet functional. + for (auto name : { NAME_MainMenu, NAME_IngameMenu }) + { + FMenuDescriptor** desc = MenuDescriptors.CheckKey(name); + if (desc != NULL && (*desc)->mType == MDESC_ListMenu) + { + FListMenuDescriptor* ld = static_cast(*desc); + for (auto& li : ld->mItems) + { + if (li->GetAction(nullptr) == NAME_MultiMenu) + { + li->mEnabled = false; + } + } + } + } +} + +//---------------------------------------------------------------------------- +// +// Implements the native looking menu used for the main menu +// and the episode/skill selection screens, i.e. the parts +// that need to look authentic +// +//---------------------------------------------------------------------------- + +class BloodListMenu : public DListMenu +{ + using Super = DListMenu; +protected: + + void PostDraw() + { + itemBloodQAV->Draw(); + } + +}; + + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- + +class BloodImageScreen : public ImageScreen +{ + CGameMenuItemQAV anim; +public: + BloodImageScreen(FImageScrollerDescriptor::ScrollerItem* desc) + : ImageScreen(desc), anim(169, 100, mDesc->text.GetChars(), false, true) + { + + } + + void Drawer() override + { + anim.Draw(); + } +}; + +class DBloodImageScrollerMenu : public DImageScrollerMenu +{ + ImageScreen* newImageScreen(FImageScrollerDescriptor::ScrollerItem* desc) override + { + if (desc->type >= 0) return DImageScrollerMenu::newImageScreen(desc); + return new BloodImageScreen(desc); + } +}; + + +//---------------------------------------------------------------------------- +// +// Menu related game interface functions +// +//---------------------------------------------------------------------------- + +void GameInterface::DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) +{ + if (!text) return; + int shade = (state != NIT_InactiveState) ? 32 : 48; + int pal = (state != NIT_InactiveState) ? 5 : 5; + if (state == NIT_SelectedState) shade = 32 - ((int)totalclock & 63); + int width, height; + int gamefont = fontnum == NIT_BigFont ? 1 : fontnum == NIT_SmallFont ? 2 : 3; + + int x = int(xpos); + int y = int(ypos); + viewGetFontInfo(gamefont, text, &width, &height); + + if (flags & LMF_Centered) + { + x -= width / 2; + } + + viewDrawText(gamefont, text, x, y, shade, pal, 0, true); +} + + +void GameInterface::MenuOpened() +{ + itemBloodQAV.reset(new CGameMenuItemQAV(160, 100, "BDRIP.QAV", true)); +} + +void GameInterface::MenuClosed() +{ + itemBloodQAV.reset(); +} + +bool GameInterface::CanSave() +{ + return (gGameStarted && gPlayer[myconnectindex].pXSprite->health != 0); +} + +void GameInterface::StartGame(FGameStartup& gs) +{ + gGameOptions.nDifficulty = gs.Skill; + gGameOptions.nEpisode = gs.Episode; + gSkill = gs.Skill; + gGameOptions.nLevel = gs.Level; + if (gDemo.at1) + gDemo.StopPlayback(); + gStartNewGame = true; + gCheatMgr.sub_5BCF4(); +} + +FSavegameInfo GameInterface::GetSaveSig() +{ + return { SAVESIG_BLD, MINSAVEVER_BLD, SAVEVER_BLD }; +} + +void GameInterface::DrawMenuCaption(const DVector2& origin, const char* text) +{ + int height; + // font #1, tile #2038. + viewGetFontInfo(1, NULL, NULL, &height); + rotatesprite(int(origin.X * 65536) + (320 << 15), 20 << 16, 65536, 0, 2038, -128, 0, 78, 0, 0, xdim - 1, ydim - 1); + viewDrawText(1, text, 160, 20 - height / 2, -128, 0, 1, false); +} + +void GameInterface::DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) +{ + if (text) + { + int width, height = 0; + viewGetFontInfo(0, "T", &width, &height); + + auto lines = FString(text).Split("\n"); + int y = 100 - (height * lines.Size() / 2); + for (auto& l : lines) + { + int lheight = 0; + viewGetFontInfo(0, l, &width, &lheight); + int x = 160 - width / 2; + viewDrawText(0, l, x, y, 0, 0, 0, false); + y += height; + } + } +} + +void GameInterface::QuitToTitle() +{ + if (gGameOptions.nGameType == 0 || numplayers == 1) + { + gQuitGame = true; + gRestartGame = true; + } + else + gQuitRequest = 2; +} + +END_BLD_NS + +//---------------------------------------------------------------------------- +// +// Class registration +// +//---------------------------------------------------------------------------- + + +static TMenuClassDescriptor _lm("Blood.ListMenu"); +static TMenuClassDescriptor _im("Blood.ImageScrollerMenu"); + +void RegisterBloodMenus() +{ + menuClasses.Push(&_lm); + menuClasses.Push(&_im); +} diff --git a/source/blood/src/db.cpp b/source/blood/src/db.cpp index 1e37a3c1f..99f5a47cf 100644 --- a/source/blood/src/db.cpp +++ b/source/blood/src/db.cpp @@ -50,99 +50,6 @@ char qsprite_filler[kMaxSprites], qsector_filler[kMaxSectors]; int gVisibility; bool gModernMap = false; -const char *gItemText[] = { - "Skull Key", - "Eye Key", - "Fire Key", - "Dagger Key", - "Spider Key", - "Moon Key", - "Key 7", - "Doctor's Bag", - "Medicine Pouch", - "Life Essence", - "Life Seed", - "Red Potion", - "Feather Fall", - "Limited Invisibility", - "INVULNERABILITY", - "Boots of Jumping", - "Raven Flight", - "Guns Akimbo", - "Diving Suit", - "Gas mask", - "Clone", - "Crystal Ball", - "Decoy", - "Doppleganger", - "Reflective shots", - "Beast Vision", - "ShadowCloak", - "Rage shroom", - "Delirium Shroom", - "Grow shroom", - "Shrink shroom", - "Death mask", - "Wine Goblet", - "Wine Bottle", - "Skull Grail", - "Silver Grail", - "Tome", - "Black Chest", - "Wooden Chest", - "Asbestos Armor", - "Basic Armor", - "Body Armor", - "Fire Armor", - "Spirit Armor", - "Super Armor", - "Blue Team Base", - "Red Team Base", - "Blue Flag", - "Red Flag", - "DUMMY", - "Level map", -}; - -const char *gAmmoText[] = { - "Spray can", - "Bundle of TNT*", - "Bundle of TNT", - "Case of TNT", - "Proximity Detonator", - "Remote Detonator", - "Trapped Soul", - "4 shotgun shells", - "Box of shotgun shells", - "A few bullets", - "Voodoo Doll", - "OBSOLETE", - "Full drum of bullets", - "Tesla Charge", - "OBSOLETE", - "OBSOLETE", - "Flares", - "OBSOLETE", - "OBSOLETE", - "Gasoline Can", - NULL, -}; - -const char *gWeaponText[] = { - "RANDOM", - "Sawed-off", - "Tommy Gun", - "Flare Pistol", - "Voodoo Doll", - "Tesla Cannon", - "Napalm Launcher", - "Pitchfork", - "Spray Can", - "Dynamite", - "Life Leech", -}; - - void dbCrypt(char *pPtr, int nLength, int nKey) { diff --git a/source/blood/src/demo.cpp b/source/blood/src/demo.cpp index 6b1eb8c11..596ac9bc9 100644 --- a/source/blood/src/demo.cpp +++ b/source/blood/src/demo.cpp @@ -39,7 +39,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gamemenu.h" #include "globals.h" #include "levels.h" -#include "menu.h" #include "messages.h" #include "misc.h" #include "music.h" @@ -49,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "i_specialpaths.h" #include "view.h" #include "gamecontrol.h" +#include "menu/menu.h" BEGIN_BLD_NS @@ -61,10 +61,7 @@ void ReadGameOptionsLegacy(GAMEOPTIONS &gameOptions, GAMEOPTIONSLEGACY &gameOpti gameOptions.nEpisode = gameOptionsLegacy.nEpisode; gameOptions.nLevel = gameOptionsLegacy.nLevel; strcpy(gameOptions.zLevelName, gameOptionsLegacy.zLevelName); - strcpy(gameOptions.zLevelSong, gameOptionsLegacy.zLevelSong); gameOptions.nTrackNumber = gameOptionsLegacy.nTrackNumber; - strcpy(gameOptions.szSaveGameName, gameOptionsLegacy.szSaveGameName); - strcpy(gameOptions.szUserGameName, gameOptionsLegacy.szUserGameName); gameOptions.nSaveGameSlot = gameOptionsLegacy.nSaveGameSlot; gameOptions.picEntry = gameOptionsLegacy.picEntry; gameOptions.uMapCRC = gameOptionsLegacy.uMapCRC; @@ -214,16 +211,14 @@ bool CDemo::SetupPlayback(const char *pzFile) at1 = 0; if (pzFile) { - hPFile = fopenFileReader(pzFile, 0); - if (!hPFile.isOpen()) + if (!hPFile.OpenFile(pzFile)) return false; } else { if (!pCurrentDemo) return false; - hPFile = fopenFileReader(pCurrentDemo->zName, 0); - if (hPFile.isOpen()) + if (!hPFile.OpenFile(pCurrentDemo->zName)) return false; } hPFile.Read(&atf, sizeof(DEMOHEADER)); @@ -280,9 +275,6 @@ void CDemo::ProcessKeys(void) { switch (gInputMode) { - case kInputMenu: - gGameMenuMgr.Process(); - break; case kInputMessage: gPlayerMsg.ProcessKeys(); break; @@ -293,14 +285,7 @@ void CDemo::ProcessKeys(void) { switch (nKey) { - case 1: - if (!CGameMenuMgr::m_bActive) - { - gGameMenuMgr.Push(&menuMain, -1); - at2 = 1; - } - break; - case 0x58: + case sc_F12: gViewIndex = connectpoint2[gViewIndex]; if (gViewIndex == -1) gViewIndex = connecthead; @@ -321,21 +306,12 @@ void CDemo::Playback(void) inputState.SetBindsEnabled(false); ready2send = 0; int v4 = 0; - if (!CGameMenuMgr::m_bActive) - { - gGameMenuMgr.Push(&menuMain, -1); - at2 = 1; - } gNetFifoClock = totalclock; gViewMode = 3; _DEMOPLAYBACK: while (at1 && !gQuitGame) { - if (handleevents() && quitevent) - { - inputState.SetKeyStatus(sc_Escape, 1); - quitevent = 0; - } + handleevents(); MUSIC_Update(); while (totalclock >= gNetFifoClock && !gQuitGame) { @@ -407,8 +383,6 @@ _DEMOPLAYBACK: if (G_FPSLimit()) { viewDrawScreen(); - if (gInputMode == kInputMenu && CGameMenuMgr::m_bActive) - gGameMenuMgr.Draw(); videoNextPage(); } if (TestBitString(gotpic, 2342)) @@ -435,8 +409,8 @@ void CDemo::LoadDemoInfo(void) D_AddWildFile(demos, zFN); for (auto &filename : demos) { - auto hFile = fopenFileReader(filename, 0); - if (!hFile.isOpen()) + FileReader hFile; + if (!hFile.OpenFile(filename)) ThrowError("Error loading demo file header."); hFile.Read(&atf, sizeof(atf)); #if B_BIG_ENDIAN == 1 diff --git a/source/blood/src/endgame.cpp b/source/blood/src/endgame.cpp index d453362e6..4a55bf6d5 100644 --- a/source/blood/src/endgame.cpp +++ b/source/blood/src/endgame.cpp @@ -33,13 +33,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "globals.h" #include "levels.h" #include "loadsave.h" -#include "menu.h" +#include "gamemenu.h" #include "network.h" #include "player.h" #include "sound.h" #include "view.h" #include "messages.h" #include "statistics.h" +#include "gamemenu.h" +#include "gstrings.h" BEGIN_BLD_NS @@ -52,27 +54,27 @@ void CEndGameMgr::Draw(void) { viewLoadingScreenWide(); int nHeight; - gMenuTextMgr.GetFontInfo(1, NULL, NULL, &nHeight); + viewGetFontInfo(1, NULL, NULL, &nHeight); rotatesprite(160<<16, 20<<16, 65536, 0, 2038, -128, 0, 6, 0, 0, xdim-1, ydim-1); int nY = 20 - nHeight / 2; if (gGameOptions.nGameType == 0) { - viewDrawText(1, "LEVEL STATS", 160, nY, -128, 0, 1, 0); + viewDrawText(1, GStrings("TXTB_LEVELSTATS"), 160, nY, -128, 0, 1, 0); if (CCheatMgr::m_bPlayerCheated) { - viewDrawText(3, ">>> YOU CHEATED! <<<", 160, 32, -128, 0, 1, 1); + viewDrawText(3, GStrings("TXTB_CHESTED"), 160, 32, -128, 0, 1, 1); } gKillMgr.Draw(); gSecretMgr.Draw(); } else { - viewDrawText(1, "FRAG STATS", 160, nY, -128, 0, 1, 0); + viewDrawText(1, GStrings("TXTB_FRAGSTATS"), 160, nY, -128, 0, 1, 0); gKillMgr.Draw(); } if (/*dword_28E3D4 != 1 && */((int)totalclock&32)) { - viewDrawText(3, "PRESS A KEY TO CONTINUE", 160, 134, -128, 0, 1, 1); + viewDrawText(3, GStrings("PRESSKEY"), 160, 134, -128, 0, 1, 1); } } @@ -163,18 +165,18 @@ void CKillMgr::Draw(void) char pBuffer[40]; if (gGameOptions.nGameType == 0) { - viewDrawText(1, "KILLS:", 75, 50, -128, 0, 0, 1); + viewDrawText(1, FStringf("%s:", GStrings("KILLS")), 75, 50, -128, 0, 0, 1); sprintf(pBuffer, "%2d", at4); viewDrawText(1, pBuffer, 160, 50, -128, 0, 0, 1); - viewDrawText(1, "OF", 190, 50, -128, 0, 0, 1); + viewDrawText(1, GStrings("OF"), 190, 50, -128, 0, 0, 1); sprintf(pBuffer, "%2d", at0); viewDrawText(1, pBuffer, 220, 50, -128, 0, 0, 1); } else { viewDrawText(3, "#", 85, 35, -128, 0, 0, 1); - viewDrawText(3, "NAME", 100, 35, -128, 0, 0, 1); - viewDrawText(3, "FRAGS", 210, 35, -128, 0, 0, 1); + viewDrawText(3, GStrings("NAME"), 100, 35, -128, 0, 0, 1); + viewDrawText(3, GStrings("FRAGS"), 210, 35, -128, 0, 0, 1); int nStart = 0; int nEnd = gInitialNetPlayers; //if (dword_28E3D4 == 1) @@ -218,28 +220,21 @@ void CSecretMgr::Found(int nType) } else at8++; if (gGameOptions.nGameType == 0) { - switch (Random(2)) { - case 0: - viewSetMessage("A secret is revealed.", 0, MESSAGE_PRIORITY_SECRET); - break; - case 1: - viewSetMessage("You found a secret.", 0, MESSAGE_PRIORITY_SECRET); - break; - } + viewSetMessage(GStrings(FStringf("TXT_SECRET%d", Random(2))), 0, MESSAGE_PRIORITY_SECRET); } } void CSecretMgr::Draw(void) { char pBuffer[40]; - viewDrawText(1, "SECRETS:", 75, 70, -128, 0, 0, 1); + viewDrawText(1, FStringf("%s:", GStrings("TXT_SECRETS")), 75, 70, -128, 0, 0, 1); sprintf(pBuffer, "%2d", at4); viewDrawText(1, pBuffer, 160, 70, -128, 0, 0, 1); - viewDrawText(1, "OF", 190, 70, -128, 0, 0, 1); + viewDrawText(1, GStrings("OF"), 190, 70, -128, 0, 0, 1); sprintf(pBuffer, "%2d", at0); viewDrawText(1, pBuffer, 220, 70, -128, 0, 0, 1); if (at8 > 0) - viewDrawText(1, "YOU FOUND A SUPER SECRET!", 160, 100, -128, 2, 1, 1); + viewDrawText(1, GStrings("TXT_SUPERSECRET"), 160, 100, -128, 2, 1, 1); } void CSecretMgr::Clear(void) diff --git a/source/blood/src/gamemenu.cpp b/source/blood/src/gamemenu.cpp index 7e6fd143e..4ce789220 100644 --- a/source/blood/src/gamemenu.cpp +++ b/source/blood/src/gamemenu.cpp @@ -33,2961 +33,31 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "globals.h" #include "inifile.h" #include "levels.h" -#include "menu.h" +#include "gamemenu.h" #include "qav.h" +#include "demo.h" #include "resource.h" #include "view.h" #include "c_bind.h" - -bool ShowOptionMenu(); +#include "gstrings.h" BEGIN_BLD_NS -CMenuTextMgr gMenuTextMgr; -CGameMenuMgr gGameMenuMgr; -extern CGameMenuItemPicCycle itemSorryPicCycle; -extern CGameMenuItemQAV itemBloodQAV; - -CMenuTextMgr::CMenuTextMgr() -{ - at0 = -1; -} - -static char buffer[21][45]; - -void CMenuTextMgr::DrawText(const char *pString, int nFont, int x, int y, int nShade, int nPalette, bool shadow ) -{ - viewDrawText(nFont, pString, x, y, nShade, nPalette, 0, shadow); -} - -void CMenuTextMgr::GetFontInfo(int nFont, const char *pString, int *pXSize, int *pYSize) -{ - if (nFont < 0 || nFont >= 5) - return; - viewGetFontInfo(nFont, pString, pXSize, pYSize); -} - -bool CGameMenuMgr::m_bInitialized = false; -bool CGameMenuMgr::m_bActive = false; -bool CGameMenuMgr::m_bScanning = false; - -CGameMenuMgr::CGameMenuMgr() -{ - dassert(!m_bInitialized); - m_bInitialized = true; - Clear(); -} - -CGameMenuMgr::~CGameMenuMgr() -{ - m_bInitialized = false; - Clear(); -} - -void CGameMenuMgr::InitializeMenu(void) -{ - if (pActiveMenu) - { - CGameMenuEvent event; - event.at0 = kMenuEventInit; - event.at2 = 0; - pActiveMenu->Event(event); - } -} - -void CGameMenuMgr::DeInitializeMenu(void) -{ - if (pActiveMenu) - { - CGameMenuEvent event; - event.at0 = kMenuEventDeInit; - event.at2 = 0; - pActiveMenu->Event(event); - } -} - -bool CGameMenuMgr::Push(CGameMenu *pMenu, int nItem) -{ - if (nMenuPointer == 0) - { - m_mouselastactivity = -M_MOUSETIMEOUT; - m_mousewake_watchpoint = 0; - mouseLockToWindow(0); - //mouseMoveToCenter(); - inputState.mouseReadAbs(&m_prevmousepos); - } - dassert(pMenu != NULL); - if (nMenuPointer == 8) - return false; - pActiveMenu = pMenuStack[nMenuPointer] = pMenu; - nMenuPointer++; - if (nItem >= 0) - pMenu->SetFocusItem(nItem); - m_bActive = true; - gInputMode = kInputMenu; - InitializeMenu(); - m_menuchange_watchpoint = 1; - m_mousecaught = 1; - return true; -} - -void CGameMenuMgr::Pop(void) -{ - if (nMenuPointer > 0) - { - DeInitializeMenu(); - nMenuPointer--; - if (nMenuPointer == 0) - Deactivate(); - else - pActiveMenu = pMenuStack[nMenuPointer-1]; - - m_menuchange_watchpoint = 1; - } - m_mousecaught = 1; -} - -void CGameMenuMgr::PostPop(void) -{ - m_postPop = true; -} - -void CGameMenuMgr::Draw(void) -{ - if (pActiveMenu) - { - if (GUICapture & 2) - { - ImGui_Begin_Frame(); - bool b = true; - videoFadeToBlack(1); -#if 0 - ImGui::ShowDemoWindow(&b); - if (!b) -#else - if (!ShowOptionMenu()) -#endif - { - GUICapture &= ~2; - GUICapture |= 4; - Pop(); - } - return; - } - - - pActiveMenu->Draw(); - viewUpdatePages(); - } - - if (m_postPop) - { - Pop(); - m_postPop = false; - } - - int32_t mousestatus = inputState.mouseReadAbs(&m_mousepos); - if (mousestatus && inputState.mouseClickState() == MOUSE_PRESSED) - m_mousedownpos = m_mousepos; - - int16_t mousetile = 1043; // red arrow - if (tilesiz[mousetile].x > 0 && mousestatus) - { - if (!MOUSEACTIVECONDITION) - m_mousewake_watchpoint = 1; - - if (MOUSEACTIVECONDITIONAL(inputState.mouseAdvanceClickState()) || m_mousepos.x != m_prevmousepos.x || m_mousepos.y != m_prevmousepos.y) - { - m_prevmousepos = m_mousepos; - m_mouselastactivity = (int)totalclock; - } - else - m_mousewake_watchpoint = 0; - - m_mousecaught = 0; - } - else - { - m_mouselastactivity = -M_MOUSETIMEOUT; - - m_mousewake_watchpoint = 0; - } - - // Display the mouse cursor, except on touch devices. - if (MOUSEACTIVECONDITION) - { - vec2_t cursorpos = { m_mousepos.x + (7 << 16), m_mousepos.y + (6 << 16) }; - - if ((unsigned) mousetile < MAXTILES) - { - int32_t scale = 65536; - int16_t rotate = 768; - uint32_t stat = 2|4|8; - int8_t alpha = MOUSEALPHA; //CURSORALPHA; - rotatesprite_fs_alpha(cursorpos.x, cursorpos.y, scale, rotate, mousetile, 0, 0, stat, alpha); - } - } - else - inputState.clearMouseClickState(); - -} - -void CGameMenuMgr::Clear(void) -{ - pActiveMenu = NULL; - memset(pMenuStack, 0, sizeof(pMenuStack)); - nMenuPointer = 0; - m_postPop = false; -} - -void CGameMenuMgr::Process(void) -{ - if (!pActiveMenu) - return; - - if (m_menuchange_watchpoint > 0) - m_menuchange_watchpoint++; - - CGameMenuEvent event; - event.at0 = 0; - event.at2 = 0; - char key; - if (!pActiveMenu->MouseEvent(event) && (key = inputState.keyGetScan()) != 0 ) - { - inputState.keyFlushScans(); - inputState.keyFlushChars(); - event.at2 = key; - switch (key) - { - case sc_Escape: - event.at0 = kMenuEventEscape; - break; - case sc_Tab: - if (inputState.ShiftPressed()) - event.at0 = kMenuEventUp; - else - event.at0 = kMenuEventDown; - break; - case sc_UpArrow: - case sc_kpad_8: - event.at0 = kMenuEventUp; - gGameMenuMgr.m_mouselastactivity = -M_MOUSETIMEOUT; - break; - case sc_DownArrow: - case sc_kpad_2: - event.at0 = kMenuEventDown; - gGameMenuMgr.m_mouselastactivity = -M_MOUSETIMEOUT; - break; - case sc_Enter: - case sc_kpad_Enter: - event.at0 = kMenuEventEnter; - break; - case sc_Space: - event.at0 = kMenuEventSpace; - break; - case sc_LeftArrow: - case sc_kpad_4: - event.at0 = kMenuEventLeft; - break; - case sc_RightArrow: - case sc_kpad_6: - event.at0 = kMenuEventRight; - break; - case sc_Delete: - case sc_kpad_Period: - event.at0 = kMenuEventDelete; - break; - case sc_BackSpace: - event.at0 = kMenuEventBackSpace; - break; - default: - event.at0 = kMenuEventKey; - break; - } - } - if (pActiveMenu->Event(event)) - Pop(); - - if (m_menuchange_watchpoint >= 3) - m_menuchange_watchpoint = 0; -} - -void CGameMenuMgr::Deactivate(void) -{ - Clear(); - inputState.keyFlushScans(); - inputState.keyFlushChars(); - m_bActive = false; - - mouseLockToWindow(1); - gInputMode = kInputGame; -} - -bool CGameMenuMgr::MouseOutsideBounds(vec2_t const * const pos, const int32_t x, const int32_t y, const int32_t width, const int32_t height) -{ - return pos->x < x || pos->x >= x + width || pos->y < y || pos->y >= y + height; -} - -CGameMenu::CGameMenu() -{ - m_nItems = 0; - m_nFocus = at8 = -1; - atc = 0; -} - -CGameMenu::CGameMenu(int unk) -{ - m_nItems = 0; - m_nFocus = at8 = -1; - atc = unk; -} - -CGameMenu::~CGameMenu() -{ - if (!atc) - return; - for (int i = 0; i < m_nItems; i++) - { - if (pItemList[i] != &itemBloodQAV && pItemList[i] != &itemSorryPicCycle) - delete pItemList[i]; - } -} - -void CGameMenu::InitializeItems(CGameMenuEvent &event) -{ - for (int i = 0; i < m_nItems; i++) - { - pItemList[i]->Event(event); - } -} - -void CGameMenu::Draw(void) -{ - for (int i = 0; i < m_nItems; i++) - { - if (pItemList[i]->pPreDrawCallback) - pItemList[i]->pPreDrawCallback(pItemList[i]); - if (i == m_nFocus || (i != m_nFocus && !pItemList[i]->bNoDraw)) - pItemList[i]->Draw(); - } -} - -bool CGameMenu::Event(CGameMenuEvent &event) -{ - if (m_nItems <= 0) - return true; - switch (event.at0) - { - case kMenuEventInit: - case kMenuEventDeInit: - if (at8 >= 0) - m_nFocus = at8; - InitializeItems(event); - return false; - } - if (m_nFocus < 0) - return true; - return pItemList[m_nFocus]->Event(event); -} - -void CGameMenu::Add(CGameMenuItem *pItem, bool active) -{ - dassert(pItem != NULL); - dassert(m_nItems < kMaxGameMenuItems); - pItemList[m_nItems] = pItem; - pItem->pMenu = this; - if (active) - m_nFocus = at8 = m_nItems; - m_nItems++; -} - -void CGameMenu::SetFocusItem(int nItem) -{ - dassert(nItem >= 0 && nItem < m_nItems && nItem < kMaxGameMenuItems); - if (CanSelectItem(nItem)) - m_nFocus = at8 = nItem; -} - -void CGameMenu::SetFocusItem(CGameMenuItem *pItem) -{ - for (int i = 0; i < m_nItems; i++) - if (pItemList[i] == pItem) - { - SetFocusItem(i); - break; - } -} - -bool CGameMenu::CanSelectItem(int nItem) -{ - dassert(nItem >= 0 && nItem < m_nItems && nItem < kMaxGameMenuItems); - return pItemList[nItem]->bCanSelect && pItemList[nItem]->bEnable; -} - -void CGameMenu::FocusPrevItem(void) -{ - dassert(m_nFocus >= -1 && m_nFocus < m_nItems && m_nFocus < kMaxGameMenuItems); - int t = m_nFocus; - do - { - m_nFocus--; - if (m_nFocus < 0) - m_nFocus += m_nItems; - if (CanSelectItem(m_nFocus)) - break; - } while(t != m_nFocus); -} - -void CGameMenu::FocusNextItem(void) -{ - dassert(m_nFocus >= -1 && m_nFocus < m_nItems && m_nFocus < kMaxGameMenuItems); - int t = m_nFocus; - do - { - m_nFocus++; - if (m_nFocus >= m_nItems) - m_nFocus = 0; - if (CanSelectItem(m_nFocus)) - break; - } while(t != m_nFocus); -} - -bool CGameMenu::IsFocusItem(CGameMenuItem *pItem) -{ - if (m_nFocus < 0) - return false; - dassert(m_nFocus >= 0 && m_nFocus < m_nItems && m_nFocus < kMaxGameMenuItems); - return pItemList[m_nFocus] == pItem; -} - -bool CGameMenu::MouseEvent(CGameMenuEvent &event) -{ - if (m_nItems <= 0 || m_nFocus < 0) - return true; - return pItemList[m_nFocus]->MouseEvent(event); -} - -CGameMenuItem::CGameMenuItem() -{ - m_pzText = NULL; - m_nX = m_nY = m_nWidth = 0; - bCanSelect = 1; - bEnable = 1; - m_nFont = -1; - pMenu = NULL; - bNoDraw = 0; - pPreDrawCallback = NULL; -} - -CGameMenuItem::~CGameMenuItem() -{ -} - -bool CGameMenuItem::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventEscape: - return true; - case kMenuEventUp: - pMenu->FocusPrevItem(); - break; - case kMenuEventDown: - pMenu->FocusNextItem(); - break; - } - return false; -} - -bool CGameMenuItem::MouseEvent(CGameMenuEvent &event) -{ - event.at0 = kMenuEventNone; - if (MOUSEINACTIVECONDITIONAL(inputState.MouseGetButtons()&LEFT_MOUSE)) - { - event.at0 = kMenuEventEnter; - inputState.MouseClearButton(LEFT_MOUSE); - } - else if (inputState.MouseGetButtons()&RIGHT_MOUSE) - { - event.at0 = kMenuEventEscape; - inputState.MouseClearButton(RIGHT_MOUSE); - } - else if (inputState.MouseGetButtons()&WHEELUP_MOUSE) - { - inputState.MouseClearButton(WHEELUP_MOUSE); - event.at0 = kMenuEventUp; - } - else if (inputState.MouseGetButtons()&WHEELDOWN_MOUSE) - { - inputState.MouseClearButton(WHEELDOWN_MOUSE); - event.at0 = kMenuEventDown; - } - return event.at0 != kMenuEventNone; -} - -CGameMenuItemText::CGameMenuItemText() -{ - m_pzText = 0; - bEnable = 0; -} - -CGameMenuItemText::CGameMenuItemText(const char *a1, int a2, int a3, int a4, int a5) -{ - m_nWidth = 0; - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - at20 = a5; - bEnable = 0; -} - -void CGameMenuItemText::Draw(void) -{ - if (m_pzText) - { - int width; - int x = m_nX; - switch (at20) - { - case 1: - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - x = m_nX-width/2; - break; - case 2: - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - x = m_nX-width; - break; - } - gMenuTextMgr.DrawText(m_pzText,m_nFont, x, m_nY, -128, 0, false); - } -} - -CGameMenuItemTitle::CGameMenuItemTitle() -{ - m_pzText = 0; - bEnable = 0; -} - -CGameMenuItemTitle::CGameMenuItemTitle(const char *a1, int a2, int a3, int a4, int a5) -{ - m_nWidth = 0; - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - at20 = a5; - bEnable = 0; -} - -void CGameMenuItemTitle::Draw(void) -{ - if (m_pzText) - { - int height; - gMenuTextMgr.GetFontInfo(m_nFont, NULL, NULL, &height); - if (at20 >= 0) - rotatesprite(320<<15, m_nY<<16, 65536, 0, at20, -128, 0, 78, 0, 0, xdim-1, ydim-1); - viewDrawText(m_nFont, m_pzText, m_nX, m_nY-height/2, -128, 0, 1, false); - } -} - -CGameMenuItemZBool::CGameMenuItemZBool() -{ - at20 = false; - m_pzText = 0; - at21 = "On"; - at25 = "Off"; -} - -CGameMenuItemZBool::CGameMenuItemZBool(const char *a1, int a2, int a3, int a4, int a5, bool a6, void(*a7)(CGameMenuItemZBool *), const char *a8, const char *a9) -{ - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - m_nWidth = a5; - at20 = a6; - at29 = a7; - if (!a8) - at21 = "On"; - else - at21 = a8; - if (!a9) - at25 = "Off"; - else - at25 = a9; -} - -void CGameMenuItemZBool::Draw(void) -{ - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - if (m_pzText) - gMenuTextMgr.DrawText(m_pzText, m_nFont, m_nX, m_nY, shade, pal, false); - const char *value = at20 ? at21 : at25; - int width, height; - gMenuTextMgr.GetFontInfo(m_nFont, value, &width, &height); - gMenuTextMgr.DrawText(value, m_nFont, m_nWidth-1+m_nX-width, m_nY, shade, pal, false); - int mx = m_nX<<16; - int my = m_nY<<16; - int mw = m_nWidth<<16; - int mh = height<<16; - if (bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, mx, my, mw, mh))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, mx, my, mw, mh))) - { - pMenu->SetFocusItem(this); - } - - if (!gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousedownpos, mx, my, mw, mh)) - { - pMenu->SetFocusItem(this); - - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } - } -} - -bool CGameMenuItemZBool::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventEnter: - case kMenuEventSpace: - at20 = !at20; - if (at29) - at29(this); - return false; - } - return CGameMenuItem::Event(event); -} - -CGameMenuItemChain::CGameMenuItemChain() -{ - m_pzText = NULL; - at24 = NULL; - at28 = -1; - at2c = NULL; - at30 = 0; -} - -CGameMenuItemChain::CGameMenuItemChain(const char *a1, int a2, int a3, int a4, int a5, int a6, CGameMenu *a7, int a8, void(*a9)(CGameMenuItemChain *), int a10) -{ - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - m_nWidth = a5; - at20 = a6; - at24 = a7; - at28 = a8; - at2c = a9; - at30 = a10; -} - -void CGameMenuItemChain::Draw(void) -{ - if (!m_pzText) return; - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - int width, height; - int x = m_nX; - int y = m_nY; - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, &height); - switch (at20) - { - case 1: - x = m_nX+m_nWidth/2-width/2; - break; - case 2: - x = m_nX+m_nWidth-1-width; - break; - case 0: - default: - break; - } - gMenuTextMgr.DrawText(m_pzText, m_nFont, x, m_nY, shade, pal, true); - if (bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, x<<16, y<<16, width<<16, height<<16))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, x<<16, y<<16, width<<16, height<<16))) - { - pMenu->SetFocusItem(this); - } - - if (!gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousedownpos, x<<16, y<<16, width<<16, height<<16)) - { - pMenu->SetFocusItem(this); - - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } - } -} - -bool CGameMenuItemChain::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventEnter: - if (at2c) - at2c(this); - if (at24) - gGameMenuMgr.Push(at24, at28); - return false; - } - return CGameMenuItem::Event(event); -} - -CGameMenuItem7EA1C::CGameMenuItem7EA1C() -{ - m_pzText = NULL; - at24 = NULL; - at28 = -1; - at2c = NULL; - at30 = 0; - at34 = NULL; - at38[0] = 0; - at48[0] = 0; -} - -CGameMenuItem7EA1C::CGameMenuItem7EA1C(const char *a1, int a2, int a3, int a4, int a5, const char *a6, const char *a7, int a8, int a9, void(*a10)(CGameMenuItem7EA1C *), int a11) -{ - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - m_nWidth = a5; - at20 = a8; - at28 = a9; - at2c = a10; - at30 = a11; - strncpy(at38, a6, 15); - strncpy(at48, a7, 15); -} - -void CGameMenuItem7EA1C::Draw(void) -{ - if (!m_pzText) return; - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - int width; - int x = m_nX; - switch (at20) - { - case 1: - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - x = m_nX+m_nWidth/2-width/2; - break; - case 2: - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - x = m_nX+m_nWidth-1-width; - break; - case 0: - default: - break; - } - gMenuTextMgr.DrawText(m_pzText, m_nFont, x, m_nY, shade, pal, true); -} - -void CGameMenuItem7EA1C::Setup(void) -{ - if (!at34 || !at24) - return; - if (!at34->SectionExists(at48)) - return; - const char *title = at34->GetKeyString(at48, "Title", at48); - at24->Add(new CGameMenuItemTitle(title, 1, 160, 20, 2038), false); - at24->Add(&itemSorryPicCycle, true); - int y = 40; - for (int i = 0; i < 21; i++) - { - sprintf(buffer[i], "Line%d", i+1); - if (!at34->KeyExists(at48, buffer[i])) - break; - const char *line = at34->GetKeyString(at48, buffer[i], NULL); - if (line) - { - if (*line == 0) - { - y += 10; - continue; - } - at24->Add(new CGameMenuItemText(line, 1, 160, y, 1), false); - y += 20; - } - } - at24->Add(&itemBloodQAV, false); -} - -bool CGameMenuItem7EA1C::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventEnter: - { - if (at2c) - at2c(this); - if (at24) - delete at24; - at24 = new CGameMenu(1); - /* - DICTNODE *pRes = gGuiRes.Lookup(at38, "MNU"); - if (pRes) - { - at34 = new IniFile(gGuiRes.Load(pRes)); - Setup(); - } - */ - if (at24) - gGameMenuMgr.Push(at24, at28); - return false; - } - case kMenuEventDeInit: - if (at34) - { - delete at34; - at34 = NULL; - } - if (at24) - { - delete at24; - at24 = NULL; - } - return false; - } - return CGameMenuItem::Event(event); -} - -CGameMenuItem7EE34::CGameMenuItem7EE34() -{ - m_pzText = NULL; - at28 = NULL; - at20 = -1; - at2c = NULL; -} - -CGameMenuItem7EE34::CGameMenuItem7EE34(const char *a1, int a2, int a3, int a4, int a5, int a6) -{ - m_pzText = NULL; - at28 = NULL; - at20 = -1; - at2c = NULL; - m_nFont = a2; - m_nX = a3; - m_pzText = a1; - m_nY = a4; - m_nWidth = a5; - at24 = a6; -} - -void CGameMenuItem7EE34::Draw(void) -{ - if (!m_pzText) return; - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - int width; - int x = m_nX; - switch (at24) - { - case 1: - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - x = m_nX+m_nWidth/2-width/2; - break; - case 2: - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - x = m_nX+m_nWidth-1-width; - break; - case 0: - default: - break; - } - gMenuTextMgr.DrawText(m_pzText, m_nFont, x, m_nY, shade, pal, true); -} - -extern void SetVideoModeOld(CGameMenuItemChain *pItem); - -void CGameMenuItem7EE34::Setup(void) -{ - if (!at28) - return; - at28->Add(new CGameMenuItemTitle("Video Mode", 1, 160, 20, 2038), false); - if (!at2c) - { - at2c = new CGameMenu(1); - at2c->Add(new CGameMenuItemTitle(" Mode Change ", 1, 160, 20, 2038), false); - at2c->Add(&itemSorryPicCycle, true); - CGameMenuItem *pItem1 = new CGameMenuItemText("VIDEO MODE WAS SET", 1, 160, 90, 1); - CGameMenuItem *pItem2 = new CGameMenuItemText("NOT ALL MODES Work correctly", 1, 160, 110, 1); - CGameMenuItem *pItem3 = new CGameMenuItemText("Press ESC to exit", 3, 160, 140, 1); - at2c->Add(pItem1, false); - pItem1->bEnable = 0; - at2c->Add(pItem2, false); - pItem2->bEnable = 0; - at2c->Add(pItem3, true); - pItem3->bEnable = 1; - at2c->Add(&itemBloodQAV, false); - } - sprintf(buffer[0], "640 x 480 (default)"); - int y = 40; - at28->Add(new CGameMenuItemChain(buffer[0], 3, 0, y, 320, 1, at2c, -1, SetVideoModeOld, validmodecnt), true); - y += 20; - for (int i = 0; i < validmodecnt && i < 20; i++) - { - sprintf(buffer[i+1], "%d x %d", validmode[i].xdim, validmode[i].ydim); - at28->Add(new CGameMenuItemChain(buffer[i+1], 3, 0, y, 320, 1, at2c, -1, SetVideoModeOld, i), false); - if (validmodecnt > 10) - y += 7; - else - y += 15; - } - at28->Add(&itemBloodQAV, false); -} - -bool CGameMenuItem7EE34::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventEnter: - if (at28) - delete at28; - at28 = new CGameMenu(1); - Setup(); - if (at28) - gGameMenuMgr.Push(at28, at20); - return false; - case kMenuEventDeInit: - if (at28) - { - delete at28; - at28 = 0; - } - return false; - } - return CGameMenuItem::Event(event); -} - -CGameMenuItemChain7F2F0::CGameMenuItemChain7F2F0() -{ - at34 = -1; -} - -CGameMenuItemChain7F2F0::CGameMenuItemChain7F2F0(char *a1, int a2, int a3, int a4, int a5, int a6, CGameMenu *a7, int a8, void(*a9)(CGameMenuItemChain *), int a10) : - CGameMenuItemChain(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) -{ - at34 = a10; -} - -bool CGameMenuItemChain7F2F0::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventEnter: - if (at34 > -1) - gGameOptions.nEpisode = at34; - return CGameMenuItemChain::Event(event); - } - return CGameMenuItem::Event(event); -} - -CGameMenuItemBitmap::CGameMenuItemBitmap() -{ - m_pzText = NULL; -} - -CGameMenuItemBitmap::CGameMenuItemBitmap(const char *a1, int a2, int a3, int a4, int a5) -{ - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - at20 = a5; -} - -void CGameMenuItemBitmap::Draw(void) -{ - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (bEnable && pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - int x = m_nX; - int y = m_nY; - if (m_pzText) - { - int height; - gMenuTextMgr.DrawText(m_pzText, m_nFont, x, y, shade, pal, false); - gMenuTextMgr.GetFontInfo(m_nFont, NULL, NULL, &height); - y += height + 2; - } - rotatesprite(x<<15,y<<15, 65536, 0, at20, 0, 0, 82, 0, 0, xdim-1,ydim-1); -} - -bool CGameMenuItemBitmap::Event(CGameMenuEvent &event) -{ - if (bEnable && pMenu->IsFocusItem(this)) - pMenu->FocusNextItem(); - return CGameMenuItem::Event(event); -} - -CGameMenuItemBitmapLS::CGameMenuItemBitmapLS() -{ - m_pzText = NULL; -} - -CGameMenuItemBitmapLS::CGameMenuItemBitmapLS(const char *a1, int a2, int a3, int a4, int a5) -{ - at24 = -1; - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - at28 = a5; -} - -void CGameMenuItemBitmapLS::Draw(void) -{ - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (bEnable && pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - int x = m_nX; - int y = m_nY; - if (m_pzText) - { - int height; - gMenuTextMgr.DrawText(m_pzText, m_nFont, x, y, shade, pal, false); - gMenuTextMgr.GetFontInfo(m_nFont, NULL, NULL, &height); - y += height + 2; - } - char stat; - int16_t ang; - int picnum; - if (at24 == -1) - { - stat = 66; - ang = 0; - picnum = at28; - } - else - { - ang = 512; - stat = 70; - picnum = at24; - } - rotatesprite(200<<15,215<<15,32768, ang, picnum, 0, 0, stat, 0, 0, xdim-1, ydim-1); -} - -bool CGameMenuItemBitmapLS::Event(CGameMenuEvent &event) -{ - if (bEnable && pMenu->IsFocusItem(this)) - pMenu->FocusNextItem(); - return CGameMenuItem::Event(event); -} - -CGameMenuItemKeyList::CGameMenuItemKeyList() -{ - m_pzText = NULL; - m_nFont = 3; - m_nX = 0; - m_nY = 0; - nRows = 0; - nTopDelta = 0; - nFocus = 0; - nGameFuncs = 0; - bScan = false; -} - -CGameMenuItemKeyList::CGameMenuItemKeyList(const char *a1, int a2, int a3, int a4, int a5, int a6, int a7, void(*a8)(CGameMenuItemKeyList *)) -{ - nTopDelta = 0; - nFocus = 0; - bScan = false; - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - m_nWidth = a5; - nRows = a6; - pCallback = a8; - nGameFuncs = a7; -} - -void CGameMenuItemKeyList::Scan(void) -{ - inputState.keyFlushChars(); - inputState.keyFlushScans(); - inputState.ClearKeysDown(); - bScan = true; -} - -void CGameMenuItemKeyList::Draw(void) -{ - char buffer[40]; - int width, height; - int shade; - gMenuTextMgr.GetFontInfo(m_nFont, NULL, NULL, &height); - int y = m_nY; - int k = nFocus - nTopDelta; - int nNewFocus = nFocus; - bool bClick = false; - for (int i = 0; i < nRows; i++, y += height, k++) - { - auto keys = Bindings.GetKeysForCommand(buttonMap.GetButtonName(k)); - FString text = C_NameKeys(keys.Data(), std::min(keys.Size(), 2u)); - sprintf(buffer, "%s", buttonMap.GetButtonName(k)); - - if (k == nFocus) - { - shade = 32; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - viewDrawText(3, buffer, m_nX, y, shade, 0, 0, false); - const char *sVal; - if (bScan && ((int)totalclock & 32)) - sVal = "____"; - else - sVal = text; - gMenuTextMgr.GetFontInfo(m_nFont, sVal, &width, 0); - viewDrawText(m_nFont, sVal, m_nX+m_nWidth-1-width, y, shade, 0, 0, false); - } - else - { - viewDrawText(3, buffer, m_nX, y, 24, 0, 0, false); - gMenuTextMgr.GetFontInfo(m_nFont, text, &width, 0); - viewDrawText(m_nFont, text, m_nX+m_nWidth-1-width, y, 24, 0, 0, false); - } - int mx = m_nX<<16; - int my = y<<16; - int mw = m_nWidth<<16; - int mh = height<<16; - if (!bScan && bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, mx, my, mw, mh))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, mx, my, mw, mh))) - { - nNewFocus = k; - } - - if (!gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousedownpos, mx, my, mw, mh)) - { - nNewFocus = k; - bClick = true; - } - } - } - nTopDelta += nNewFocus-nFocus; - nFocus = nNewFocus; - if (bClick) - { - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } -} - -bool CGameMenuItemKeyList::Event(CGameMenuEvent &event) -{ - if (bScan) - { - if (inputState.GetLastScanCode() && inputState.GetLastScanCode() != sc_Pause) - { - if (inputState.keyBufferWaiting()) - inputState.keyGetChar(); - - Bindings.SetBind(inputState.GetLastScanCode(), buttonMap.GetButtonName(nFocus)); - inputState.keyFlushChars(); - inputState.keyFlushScans(); - inputState.ClearKeysDown(); - inputState.keyFlushScans(); - inputState.keyFlushChars(); - bScan = 0; - } - return false; - } - switch (event.at0) - { - case kMenuEventUp: - if (event.at2 == sc_Tab || nFocus == 0) - { - pMenu->FocusPrevItem(); - return false; - } - nFocus--; - if (nTopDelta > 0) - nTopDelta--; - return false; - case kMenuEventDown: - if (event.at2 == sc_Tab || nFocus == nGameFuncs-1) - { - pMenu->FocusNextItem(); - return false; - } - nFocus++; - if (nTopDelta+1 < nRows) - nTopDelta++; - return false; - case kMenuEventEnter: - if (pCallback) - pCallback(this); - Scan(); - return false; - case kMenuEventBackSpace: - case kMenuEventDelete: - Bindings.UnbindACommand(buttonMap.GetButtonName(nFocus)); - return false; - case kMenuEventScrollUp: - if (nFocus-nTopDelta > 0) - { - nTopDelta++; - if (nTopDelta>0) - { - nFocus--; - nTopDelta--; - } - } - return false; - case kMenuEventScrollDown: - if (nFocus-nTopDelta+nRows < nGameFuncs) - { - nTopDelta--; - if (nTopDelta+1 < nRows) - { - nFocus++; - nTopDelta++; - } - } - return false; - } - return CGameMenuItem::Event(event); -} - -bool CGameMenuItemKeyList::MouseEvent(CGameMenuEvent &event) -{ - event.at0 = kMenuEventNone; - if (MOUSEACTIVECONDITIONAL(inputState.MouseGetButtons()&WHEELUP_MOUSE)) - { - gGameMenuMgr.m_mouselastactivity = (int)totalclock; - inputState.MouseClearButton(WHEELUP_MOUSE); - event.at0 = kMenuEventScrollUp; - } - else if (MOUSEACTIVECONDITIONAL(inputState.MouseGetButtons()&WHEELDOWN_MOUSE)) - { - gGameMenuMgr.m_mouselastactivity = (int)totalclock; - inputState.MouseClearButton(WHEELDOWN_MOUSE); - event.at0 = kMenuEventScrollDown; - } - else - return CGameMenuItem::MouseEvent(event); - return event.at0 != kMenuEventNone; -} - -CGameMenuItemSlider::CGameMenuItemSlider() -{ - m_pzText = NULL; - m_nFont = -1; - m_nX = 0; - m_nY = 0; - nValue = 0; - nRangeLow = 0; - nStep = 0; - pCallback = NULL; - pValue = NULL; - nSliderTile = 2204; - nCursorTile = 2028; - nShowValue = kMenuSliderNone; -} - -CGameMenuItemSlider::CGameMenuItemSlider(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, int _nValue, int _nRangeLow, int _nRangeHigh, int _nStep, void(*_pCallback)(CGameMenuItemSlider *), int _nSliderTile, int _nCursorTile, int _nShowValue) -{ - m_pzText = _pzText; - m_nFont = _nFont; - m_nX = _nX; - m_nY = _nY; - m_nWidth = _nWidth; - nRangeLow = _nRangeLow; - nRangeHigh = _nRangeHigh; - nStep = _nStep; - nValue = ClipRange(_nValue, nRangeLow, nRangeHigh); - pCallback = _pCallback; - nSliderTile = 2204; - nCursorTile = 2028; - if (_nSliderTile >= 0) - nSliderTile = _nSliderTile; - if (_nCursorTile >= 0) - nCursorTile = _nCursorTile; - nShowValue = _nShowValue; -} - -CGameMenuItemSlider::CGameMenuItemSlider(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, int *pnValue, int _nRangeLow, int _nRangeHigh, int _nStep, void(*_pCallback)(CGameMenuItemSlider *), int _nSliderTile, int _nCursorTile, int _nShowValue) -{ - m_pzText = _pzText; - m_nFont = _nFont; - m_nX = _nX; - m_nY = _nY; - m_nWidth = _nWidth; - nRangeLow = _nRangeLow; - nRangeHigh = _nRangeHigh; - nStep = _nStep; - dassert(pnValue != NULL); - pValue = pnValue; - nValue = ClipRange(*pnValue, nRangeLow, nRangeHigh); - pCallback = _pCallback; - nSliderTile = 2204; - nCursorTile = 2028; - if (_nSliderTile >= 0) - nSliderTile = _nSliderTile; - if (_nCursorTile >= 0) - nCursorTile = _nCursorTile; - nShowValue = _nShowValue; -} - -void CGameMenuItemSlider::Draw(void) -{ - char buffer[16]; - int height; - nValue = pValue ? *pValue : nValue; - gMenuTextMgr.GetFontInfo(m_nFont, NULL, NULL, &height); - int shade = bEnable ? 32 : 48; - int shade2 = bEnable ? 0 : 16; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - if (m_pzText) - gMenuTextMgr.DrawText(m_pzText, m_nFont, m_nX, m_nY, shade, pal, false); - int sliderX = m_nX+m_nWidth-1-tilesiz[nSliderTile].x/2; - rotatesprite(sliderX<<16, (m_nY+height/2)<<16, 65536, 0, nSliderTile, shade2, pal, 10, 0, 0, xdim-1, ydim-1); - int nRange = nRangeHigh - nRangeLow; - dassert(nRange > 0); - int value = nValue - nRangeLow; - int width = tilesiz[nSliderTile].x-8; - int cursorX = sliderX + ksgn(nStep)*(value * width / nRange - width / 2); - rotatesprite(cursorX<<16, (m_nY+height/2)<<16, 65536, 0, nCursorTile, shade2, pal, 10, 0, 0, xdim-1, ydim-1); - - buffer[0] = 0; - switch (nShowValue) - { - case kMenuSliderNone: - break; - case kMenuSliderValue: - sprintf(buffer, "%i ", nValue); - break; - case kMenuSliderPercent: - sprintf(buffer, "%i%% ", roundscale(value, 100, nRange)); - break; - case kMenuSliderQ16: - snprintf(buffer, 16, "%.3f ", nValue/65536.f); - break; - } - int valueWidth; - gMenuTextMgr.GetFontInfo(m_nFont, buffer, &valueWidth, NULL); - int valueX = m_nX+m_nWidth-1-tilesiz[nSliderTile].x-valueWidth; - gMenuTextMgr.DrawText(buffer, m_nFont, valueX, m_nY, 32, 0, false); - - int mx = m_nX; - int my = m_nY; - int mw = m_nWidth; - int mh = height; - if (height < tilesiz[nSliderTile].y) - { - my -= (tilesiz[nSliderTile].y-height)/2; - height = tilesiz[nSliderTile].y; - } - mx <<= 16; - my <<= 16; - mw <<= 16; - mh <<= 16; - - if (bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, mx, my, mw, mh))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, mx, my, mw, mh))) - { - pMenu->SetFocusItem(this); - } - - if (!gGameMenuMgr.m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - pMenu->SetFocusItem(this); - - int sliderx = m_nX+m_nWidth-1-tilesiz[nSliderTile].x; - int sliderwidth = tilesiz[nSliderTile].x; - int regionwidth = sliderwidth-8; - int regionx = sliderx+(sliderwidth-regionwidth)/2; - sliderx <<= 16; - sliderwidth <<= 16; - regionwidth <<= 16; - regionx <<= 16; - - // region between the x-midline of the slidepoint at the extremes slides proportionally - if (!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, regionx, my, regionwidth, mh)) - { - int dx = (gGameMenuMgr.m_mousepos.x - (regionx+regionwidth/2))*ksgn(nStep); - nValue = nRangeLow + roundscale(dx+regionwidth/2, nRange, regionwidth); - nValue = ClipRange(nValue, nRangeLow, nRangeHigh); - if (pCallback) - pCallback(this); - gGameMenuMgr.m_mousecaught = 1; - } - // region outside the x-midlines clamps to the extremes - else if (!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, sliderx, my, sliderwidth, mh)) - { - if ((gGameMenuMgr.m_mousepos.x-(regionx+regionwidth/2))*ksgn(nStep) > 0) - nValue = nRangeHigh; - else - nValue = nRangeLow; - if (pCallback) - pCallback(this); - gGameMenuMgr.m_mousecaught = 1; - } - } - } -} - -bool CGameMenuItemSlider::Event(CGameMenuEvent &event) -{ - nValue = pValue ? *pValue : nValue; - switch (event.at0) - { - case kMenuEventUp: - pMenu->FocusPrevItem(); - return false; - case kMenuEventDown: - pMenu->FocusNextItem(); - return false; - case kMenuEventLeft: - if (nStep > 0) - nValue = DecBy(nValue, nStep); - else - nValue = IncBy(nValue, -nStep); - nValue = ClipRange(nValue, nRangeLow, nRangeHigh); - if (pCallback) - pCallback(this); - return false; - case kMenuEventRight: - if (nStep >= 0) - nValue = IncBy(nValue, nStep); - else - nValue = DecBy(nValue, -nStep); - nValue = ClipRange(nValue, nRangeLow, nRangeHigh); - if (pCallback) - pCallback(this); - return false; - case kMenuEventEnter: - if (pCallback) - pCallback(this); - return false; - } - return CGameMenuItem::Event(event); -} - -bool CGameMenuItemSlider::MouseEvent(CGameMenuEvent &event) -{ - event.at0 = kMenuEventNone; - if (MOUSEINACTIVECONDITIONAL((inputState.MouseGetButtons()&LEFT_MOUSE) && (inputState.MouseGetButtons()&WHEELUP_MOUSE))) - { - inputState.MouseClearButton(WHEELUP_MOUSE); - event.at0 = kMenuEventLeft; - } - else if (MOUSEINACTIVECONDITIONAL((inputState.MouseGetButtons()&LEFT_MOUSE) && (inputState.MouseGetButtons()&WHEELDOWN_MOUSE))) - { - inputState.MouseClearButton(WHEELDOWN_MOUSE); - event.at0 = kMenuEventRight; - } - else if (inputState.MouseGetButtons()&RIGHT_MOUSE) - { - inputState.MouseClearButton(RIGHT_MOUSE); - event.at0 = kMenuEventEscape; - } - else if (inputState.MouseGetButtons()&WHEELUP_MOUSE) - { - inputState.MouseClearButton(WHEELUP_MOUSE); - inputState.MouseClearButton(LEFT_MOUSE); - event.at0 = kMenuEventUp; - } - else if (inputState.MouseGetButtons()&WHEELDOWN_MOUSE) - { - inputState.MouseClearButton(WHEELDOWN_MOUSE); - inputState.MouseClearButton(LEFT_MOUSE); - event.at0 = kMenuEventDown; - } - return event.at0 != kMenuEventNone; -} - -CGameMenuItemSliderFloat::CGameMenuItemSliderFloat() -{ - m_pzText = NULL; - m_nFont = -1; - m_nX = 0; - m_nY = 0; - fValue = 0; - fRangeLow = 0; - fStep = 0; - pCallback = NULL; - pValue = NULL; - nSliderTile = 2204; - nCursorTile = 2028; - nShowValue = kMenuSliderNone; -} - -CGameMenuItemSliderFloat::CGameMenuItemSliderFloat(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, float _fValue, float _fRangeLow, float _fRangeHigh, float _fStep, void(*_pCallback)(CGameMenuItemSliderFloat *), int _nSliderTile, int _nCursorTile, int _nShowValue) -{ - m_pzText = _pzText; - m_nFont = _nFont; - m_nX = _nX; - m_nY = _nY; - m_nWidth = _nWidth; - fRangeLow = _fRangeLow; - fRangeHigh = _fRangeHigh; - fStep = _fStep; - fValue = ClipRangeF(_fValue, fRangeLow, fRangeHigh); - pCallback = _pCallback; - nSliderTile = 2204; - nCursorTile = 2028; - if (_nSliderTile >= 0) - nSliderTile = _nSliderTile; - if (_nCursorTile >= 0) - nCursorTile = _nCursorTile; - nShowValue = _nShowValue; -} - -CGameMenuItemSliderFloat::CGameMenuItemSliderFloat(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, float *pnValue, float _fRangeLow, float _fRangeHigh, float _fStep, void(*_pCallback)(CGameMenuItemSliderFloat *), int _nSliderTile, int _nCursorTile, int _nShowValue) -{ - m_pzText = _pzText; - m_nFont = _nFont; - m_nX = _nX; - m_nY = _nY; - m_nWidth = _nWidth; - fRangeLow = _fRangeLow; - fRangeHigh = _fRangeHigh; - fStep = _fStep; - dassert(pnValue != NULL); - pValue = pnValue; - fValue = ClipRangeF(*pnValue, fRangeLow, fRangeHigh); - pCallback = _pCallback; - nSliderTile = 2204; - nCursorTile = 2028; - if (_nSliderTile >= 0) - nSliderTile = _nSliderTile; - if (_nCursorTile >= 0) - nCursorTile = _nCursorTile; - nShowValue = _nShowValue; -} - -void CGameMenuItemSliderFloat::Draw(void) -{ - char buffer[16]; - int height; - - fValue = pValue ? *pValue : fValue; - gMenuTextMgr.GetFontInfo(m_nFont, NULL, NULL, &height); - int shade = bEnable ? 32 : 48; - int shade2 = bEnable ? 0 : 16; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - if (m_pzText) - gMenuTextMgr.DrawText(m_pzText, m_nFont, m_nX, m_nY, shade, pal, false); - int sliderX = m_nX+m_nWidth-1-tilesiz[nSliderTile].x/2; - rotatesprite(sliderX<<16, (m_nY+height/2)<<16, 65536, 0, nSliderTile, shade2, pal, 10, 0, 0, xdim-1, ydim-1); - float fRange = fRangeHigh - fRangeLow; - dassert(fRange > 0); - float value = fValue - fRangeLow; - int width = tilesiz[nSliderTile].x-8; - int cursorX = sliderX + (int)(ksgnf(fStep)*(value * width / fRange - width / 2)); - rotatesprite(cursorX<<16, (m_nY+height/2)<<16, 65536, 0, nCursorTile, shade2, pal, 10, 0, 0, xdim-1, ydim-1); - - buffer[0] = 0; - switch (nShowValue) - { - case kMenuSliderNone: - break; - case kMenuSliderValue: - snprintf(buffer, 16, "%.3f ", fValue); - break; - case kMenuSliderPercent: - snprintf(buffer, 16, "%.3f%% ", value*100.f/fRange); - break; - } - int valueWidth; - gMenuTextMgr.GetFontInfo(m_nFont, buffer, &valueWidth, NULL); - int valueX = m_nX+m_nWidth-1-tilesiz[nSliderTile].x-valueWidth; - gMenuTextMgr.DrawText(buffer, m_nFont, valueX, m_nY, 32, 0, false); - - int mx = m_nX; - int my = m_nY; - int mw = m_nWidth; - int mh = height; - if (height < tilesiz[nSliderTile].y) - { - my -= (tilesiz[nSliderTile].y-height)/2; - height = tilesiz[nSliderTile].y; - } - mx <<= 16; - my <<= 16; - mw <<= 16; - mh <<= 16; - - if (bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, mx, my, mw, mh))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, mx, my, mw, mh))) - { - pMenu->SetFocusItem(this); - } - - if (!gGameMenuMgr.m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - pMenu->SetFocusItem(this); - - int sliderx = m_nX+m_nWidth-1-tilesiz[nSliderTile].x; - int sliderwidth = tilesiz[nSliderTile].x; - int regionwidth = sliderwidth-8; - int regionx = sliderx+(sliderwidth-regionwidth)/2; - sliderx <<= 16; - sliderwidth <<= 16; - regionwidth <<= 16; - regionx <<= 16; - - // region between the x-midline of the slidepoint at the extremes slides proportionally - if (!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, regionx, my, regionwidth, mh)) - { - int dx = (gGameMenuMgr.m_mousepos.x - (regionx+regionwidth/2))*ksgnf(fStep); - fValue = fRangeLow + (dx+regionwidth/2) * fRange / regionwidth; - fValue = ClipRangeF(fValue, fRangeLow, fRangeHigh); - if (pCallback) - pCallback(this); - gGameMenuMgr.m_mousecaught = 1; - } - // region outside the x-midlines clamps to the extremes - else if (!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, sliderx, my, sliderwidth, mh)) - { - if ((gGameMenuMgr.m_mousepos.x-(regionx+regionwidth/2))*ksgnf(fStep) > 0) - fValue = fRangeHigh; - else - fValue = fRangeLow; - if (pCallback) - pCallback(this); - gGameMenuMgr.m_mousecaught = 1; - } - } - } -} - -bool CGameMenuItemSliderFloat::Event(CGameMenuEvent &event) -{ - fValue = pValue ? *pValue : fValue; - switch (event.at0) - { - case kMenuEventUp: - pMenu->FocusPrevItem(); - return false; - case kMenuEventDown: - pMenu->FocusNextItem(); - return false; - case kMenuEventLeft: - if (fStep > 0) - fValue -= fStep; - else - fValue += fStep; - fValue = ClipRangeF(fValue, fRangeLow, fRangeHigh); - if (pCallback) - pCallback(this); - return false; - case kMenuEventRight: - if (fStep >= 0) - fValue += fStep; - else - fValue -= fStep; - fValue = ClipRangeF(fValue, fRangeLow, fRangeHigh); - if (pCallback) - pCallback(this); - return false; - case kMenuEventEnter: - if (pCallback) - pCallback(this); - return false; - } - return CGameMenuItem::Event(event); -} - -CGameMenuItemZEdit::CGameMenuItemZEdit() -{ - m_pzText = NULL; - m_nFont = -1; - m_nX = 0; - m_nY = 0; - at20 = NULL; - at24 = 0; - at32 = 0; - at2c = 0; - at30 = 0; - at28 = 0; - at31 = 1; -} - -CGameMenuItemZEdit::CGameMenuItemZEdit(const char *a1, int a2, int a3, int a4, int a5, char *a6, int a7, char a8, void(*a9)(CGameMenuItemZEdit *, CGameMenuEvent *), int a10) -{ - at30 = 0; - at31 = 1; - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - m_nWidth = a5; - at20 = a6; - at24 = a7; - at32 = a8; - at2c = a9; - at28 = a10; -} - -void CGameMenuItemZEdit::AddChar(char ch) -{ - int i = strlen(at20); - if (i + 1 < at24) - { - at20[i] = ch; - at20[i + 1] = 0; - } -} - -void CGameMenuItemZEdit::BackChar(void) -{ - int i = strlen(at20); - if (i > 0) - at20[i - 1] = 0; -} - -void CGameMenuItemZEdit::Draw(void) -{ - int height, width, textWidth = 0; - gMenuTextMgr.GetFontInfo(m_nFont, NULL, &width, &height); - if (at20) - gMenuTextMgr.GetFontInfo(m_nFont, at20, &textWidth, NULL); - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - if (at30) - shade = -128; - if (m_pzText) - gMenuTextMgr.DrawText(m_pzText, m_nFont, m_nX, m_nY, shade, pal, false); - int x = m_nX+m_nWidth-1-textWidth;//(at24+1)*width; - if (at20 && *at20) - { - int width; - gMenuTextMgr.GetFontInfo(m_nFont, at20, &width, NULL); - int shade2; - if (at32) - { - if (at30) - shade2 = -128; - else - shade2 = shade; - } - else - { - if (at30) - shade2 = shade; - else - shade2 = 32; - } - gMenuTextMgr.DrawText(at20, m_nFont, x, m_nY, shade2, pal, false); - x += width; - } - if (at30 && ((int)totalclock & 32)) - gMenuTextMgr.DrawText("_", m_nFont, x, m_nY, shade, 0, false); - - int mx = m_nX<<16; - int my = m_nY<<16; - int mw = m_nWidth<<16; - int mh = height<<16; - - if (bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, mx, my, mw, mh))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, mx, my, mw, mh))) - { - pMenu->SetFocusItem(this); - } - - if (!gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousedownpos, mx, my, mw, mh)) - { - pMenu->SetFocusItem(this); - - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } - } -} - -bool CGameMenuItemZEdit::Event(CGameMenuEvent &event) -{ - static char buffer[256]; - // Hack - if (event.at2 == sc_kpad_2 || event.at2 == sc_kpad_4 || event.at2 == sc_kpad_6 || event.at2 == sc_kpad_8) - event.at0 = kMenuEventKey; - switch (event.at0) - { - case kMenuEventEscape: - if (at30) - { - strncpy(at20, buffer, at24); - at20[at24-1] = 0; - at30 = 0; - return false; - } - return true; - case kMenuEventEnter: - if (!at31) - { - if (at2c) - at2c(this, &event); - return false; - } - if (at30) - { - if (at2c) - at2c(this, &event); - at30 = 0; - return false; - } - strncpy(buffer, at20, at24); - buffer[at24-1] = 0; - at30 = 1; - return false; - case kMenuEventBackSpace: - if (at30) - BackChar(); - return false; - case kMenuEventKey: - case kMenuEventSpace: - { - char key; - if (event.at2 < 128) - { - if (inputState.ShiftPressed()) - key = g_keyAsciiTableShift[event.at2]; - else - key = g_keyAsciiTable[event.at2]; - if (at30 && (isalnum(key) || ispunct(key) || isspace(key))) - { - AddChar(key); - return false; - } - } - return CGameMenuItem::Event(event); - } - case kMenuEventUp: - if (at30) - return false; - return CGameMenuItem::Event(event); - case kMenuEventDown: - if (at30) - return false; - return CGameMenuItem::Event(event); - } - return CGameMenuItem::Event(event); -} - -CGameMenuItemZEditBitmap::CGameMenuItemZEditBitmap() -{ - m_pzText = NULL; - m_nFont = -1; - m_nX = 0; - m_nY = 0; - at20 = NULL; - at24 = 0; - at36 = 0; - at30 = NULL; - at2c = NULL; - bScan = 0; - at28 = 0; - at37 = 0; - at35 = 1; -} - -CGameMenuItemZEditBitmap::CGameMenuItemZEditBitmap(char *a1, int a2, int a3, int a4, int a5, char *a6, int a7, char a8, void(*a9)(CGameMenuItemZEditBitmap *, CGameMenuEvent *), int a10) -{ - at2c = NULL; - bScan = 0; - at35 = 1; - at37 = 0; - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - m_nWidth = a5; - at20 = a6; - at24 = a7; - at36 = a8; - at30 = a9; - at28 = a10; -} - -void CGameMenuItemZEditBitmap::AddChar(char ch) -{ - int i = strlen(at20); - if (i + 1 < at24) - { - at20[i] = ch; - at20[i + 1] = 0; - } -} - -void CGameMenuItemZEditBitmap::BackChar(void) -{ - int i = strlen(at20); - if (i > 0) - at20[i - 1] = 0; -} - -void CGameMenuItemZEditBitmap::Draw(void) -{ - int height, width; - gMenuTextMgr.GetFontInfo(m_nFont, NULL, &width, &height); - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - at2c->at24 = -1; - if (bScan) - shade = -128; - if (m_pzText) - gMenuTextMgr.DrawText(m_pzText, m_nFont, m_nX, m_nY, shade, pal, false); - int x = m_nX+m_nWidth-1-(at24+1)*width; - if (at20 && *at20) - { - int width; - gMenuTextMgr.GetFontInfo(m_nFont, at20, &width, NULL); - int shade2; - if (at36) - { - if (bScan) - shade2 = -128; - else - shade2 = shade; - } - else - { - if (bScan) - shade2 = shade; - else - shade2 = 32; - } - gMenuTextMgr.DrawText(at20, m_nFont, x, m_nY, shade2, 0, false); - x += width; - } - if (bScan && ((int)totalclock & 32)) - gMenuTextMgr.DrawText("_", m_nFont, x, m_nY, shade, pal, false); - - int mx = m_nX<<16; - int my = m_nY<<16; - int mw = m_nWidth<<16; - int mh = height<<16; - - if (!gGameMenuMgr.m_bScanning && bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, mx, my, mw, mh))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, mx, my, mw, mh))) - { - pMenu->SetFocusItem(this); - } - - if (!gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousedownpos, mx, my, mw, mh)) - { - pMenu->SetFocusItem(this); - - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } - } -} - -bool CGameMenuItemZEditBitmap::Event(CGameMenuEvent &event) -{ - static char buffer[256]; - // Hack - if (event.at2 == sc_kpad_2 || event.at2 == sc_kpad_4 || event.at2 == sc_kpad_6 || event.at2 == sc_kpad_8) - event.at0 = kMenuEventKey; - switch (event.at0) - { - case kMenuEventEscape: - if (bScan) - { - strncpy(at20, buffer, at24); - at20[at24-1] = 0; - bScan = 0; - gGameMenuMgr.m_bScanning = false; - gSaveGameActive = false; - return false; - } - gSaveGameActive = true; - return true; - case kMenuEventEnter: - if (!at35 || bScan) - { - if (at30) - at30(this, &event); - if (bScan) - { - bScan = 0; - gGameMenuMgr.m_bScanning = false; - } - gSaveGameActive = false; - inputState.ClearKeyStatus(sc_Enter); - inputState.ClearKeyStatus(sc_kpad_Enter); - return false; - } - strncpy(buffer, at20, at24); - if (at37) - at20[0] = 0; - buffer[at24-1] = 0; - bScan = 1; - gGameMenuMgr.m_bScanning = true; - return false; - case kMenuEventBackSpace: - if (bScan) - BackChar(); - return false; - case kMenuEventKey: - case kMenuEventSpace: - { - char key; - if (bScan && event.at2 < 128) - { - if (inputState.ShiftPressed()) - key = g_keyAsciiTableShift[event.at2]; - else - key = g_keyAsciiTable[event.at2]; - if (at30 && (isalnum(key) || ispunct(key) || isspace(key))) - { - AddChar(key); - return false; - } - } - return CGameMenuItem::Event(event); - } - case kMenuEventUp: - if (bScan) - return false; - return CGameMenuItem::Event(event); - case kMenuEventDown: - if (bScan) - return false; - return CGameMenuItem::Event(event); - } - return CGameMenuItem::Event(event); -} - -CGameMenuItemQAV::CGameMenuItemQAV() -{ - at20 = NULL; - at24 = NULL; - at28 = 0; - bEnable = 0; -} - -CGameMenuItemQAV::CGameMenuItemQAV(const char *a1, int a2, int a3, int a4, const char *a5, bool widescreen, bool clearbackground) -{ - m_nWidth = 0; - m_pzText = a1; - m_nFont = a2; - m_nY = a4; - at20 = a5; - m_nX = a3; - bEnable = 0; - bWideScreen = widescreen; - bClearBackground = clearbackground; -} - -void CGameMenuItemQAV::Draw(void) -{ - if (bClearBackground) - videoClearScreen(0); - if (at24) - { - ClockTicks backFC = gFrameClock; - gFrameClock = totalclock; - int nTicks = (int)totalclock - at30; - at30 = (int)totalclock; - at2c -= nTicks; - if (at2c <= 0 || at2c > at28->at10) - { - at2c = at28->at10; - } - at28->Play(at28->at10 - at2c - nTicks, at28->at10 - at2c, -1, NULL); - int wx1, wy1, wx2, wy2; - wx1 = windowxy1.x; - wy1 = windowxy1.y; - wx2 = windowxy2.x; - wy2 = windowxy2.y; - windowxy1.x = 0; - windowxy1.y = 0; - windowxy2.x = xdim-1; - windowxy2.y = ydim-1; - if (bWideScreen) - { - int xdim43 = scale(ydim, 4, 3); - int nCount = (xdim+xdim43-1)/xdim43; - int backX = at28->x; - for (int i = 0; i < nCount; i++) - { - at28->Draw(at28->at10 - at2c, 10+kQavOrientationLeft, 0, 0); - at28->x += 320; - } - at28->x = backX; - } - else - at28->Draw(at28->at10 - at2c, 10, 0, 0); - - windowxy1.x = wx1; - windowxy1.y = wy1; - windowxy2.x = wx2; - windowxy2.y = wy2; - gFrameClock = backFC; - } - - if (bEnable && !gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED) - { - pMenu->SetFocusItem(this); - - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } -} - -bool CGameMenuItemQAV::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventLeft: - case kMenuEventBackSpace: - pMenu->FocusPrevItem(); - return false; - case kMenuEventRight: - case kMenuEventEnter: - case kMenuEventSpace: - pMenu->FocusNextItem(); - return false; - case kMenuEventInit: - if (at20) - { - if (!at28) - { - at24 = gSysRes.Lookup(at20, "QAV"); - if (!at24) - ThrowError("Could not load QAV %s\n", at20); - at28 = (QAV*)gSysRes.Lock(at24); - at28->nSprite = -1; - at28->x = m_nX; - at28->y = m_nY; - at28->Preload(); - at2c = at28->at10; - at30 = (int)totalclock; - return false; - } - gSysRes.Lock(at24); - } - return false; - case kMenuEventDeInit: - if (at20 && at28) - { - gSysRes.Unlock(at24); - if (at24->LockCount() == 0) - at28 = NULL; - } - return false; - } - return CGameMenuItem::Event(event); -} - -void CGameMenuItemQAV::Reset(void) -{ - at2c = at28->at10; - at30 = (int)totalclock; -} - -CGameMenuItemZCycleSelect::CGameMenuItemZCycleSelect() -{ - m_pzText = NULL; - m_nFont = 3; - m_nX = 0; - m_nY = 0; - m_nRows = 0; - m_nTopDelta = 0; - m_nFocus = 0; - m_nItems = 0; - m_pzStrings = NULL; - m_pReturn = NULL; -} - -CGameMenuItemZCycleSelect::CGameMenuItemZCycleSelect(const char *pzText, int nFont, int nX, int nY, int nWidth, int nRows, int nItems, const char **pzStrings, int *pReturn, void(*pCallback)(CGameMenuItemZCycleSelect *)) +void drawLoadingScreen(void) { - m_nTopDelta = 0; - m_nFocus = 0; - m_pzText = pzText; - m_nFont = nFont; - m_nX = nX; - m_nY = nY; - m_nWidth = nWidth; - m_nRows = nRows; - m_pCallback = pCallback; - m_nItems = nItems; - m_pzStrings = pzStrings; - m_pReturn = pReturn; + char buffer[80]; + if (gGameOptions.nGameType == 0) + { + if (gDemo.at1) + strcpy(buffer, GStrings("TXTB_LDEMO")); + else + strcpy(buffer, GStrings("TXTB_LLEVEL")); + } + else + strcpy(buffer, GStrings(FStringf("TXTB_NETGT%d", gGameOptions.nGameType))); + viewLoadingScreen(2049, buffer, levelGetTitle(), NULL); } -void CGameMenuItemZCycleSelect::Draw(void) -{ - int height; - int shade; - gMenuTextMgr.GetFontInfo(m_nFont, NULL, NULL, &height); - int y = m_nY; - int k = m_nFocus - m_nTopDelta; - int nNewFocus = m_nFocus; - bool bClick = false; - for (int i = 0; i < m_nRows; i++, y += height, k++) - { - if (k == m_nFocus) - { - shade = 32; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - viewDrawText(3, m_pzStrings[k], m_nX, y, shade, 0, 0, false); - } - else - { - viewDrawText(3, m_pzStrings[k], m_nX, y, 24, 0, 0, false); - } - int mx = m_nX<<16; - int my = y<<16; - int mw = m_nWidth<<16; - int mh = height<<16; - if (bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, mx, my, mw, mh))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, mx, my, mw, mh))) - { - nNewFocus = k; - } - - if (!gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousedownpos, mx, my, mw, mh)) - { - nNewFocus = k; - bClick = true; - } - } - } - m_nTopDelta += nNewFocus-m_nFocus; - m_nFocus = nNewFocus; - if (bClick) - { - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } -} - -bool CGameMenuItemZCycleSelect::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventUp: - if (event.at2 == sc_Tab || m_nFocus == 0) - { - pMenu->FocusPrevItem(); - return false; - } - m_nFocus--; - if (m_nTopDelta > 0) - m_nTopDelta--; - return false; - case kMenuEventDown: - if (event.at2 == sc_Tab || m_nFocus == m_nItems-1) - { - pMenu->FocusNextItem(); - return false; - } - m_nFocus++; - if (m_nTopDelta+1 < m_nRows) - m_nTopDelta++; - return false; - case kMenuEventEnter: - if (m_pCallback) - m_pCallback(this); - *m_pReturn = m_nFocus; - return true; - case kMenuEventScrollUp: - if (m_nFocus-m_nTopDelta > 0) - { - m_nTopDelta++; - if (m_nTopDelta>0) - { - m_nFocus--; - m_nTopDelta--; - } - } - return false; - case kMenuEventScrollDown: - if (m_nFocus-m_nTopDelta+m_nRows < m_nItems) - { - m_nTopDelta--; - if (m_nTopDelta+1 < m_nRows) - { - m_nFocus++; - m_nTopDelta++; - } - } - return false; - } - return CGameMenuItem::Event(event); -} - -bool CGameMenuItemZCycleSelect::MouseEvent(CGameMenuEvent &event) -{ - event.at0 = kMenuEventNone; - if (MOUSEACTIVECONDITIONAL(inputState.MouseGetButtons()&WHEELUP_MOUSE)) - { - gGameMenuMgr.m_mouselastactivity = (int)totalclock; - inputState.MouseClearButton(WHEELUP_MOUSE); - event.at0 = kMenuEventScrollUp; - } - else if (MOUSEACTIVECONDITIONAL(inputState.MouseGetButtons()&WHEELDOWN_MOUSE)) - { - gGameMenuMgr.m_mouselastactivity = (int)totalclock; - inputState.MouseClearButton(WHEELDOWN_MOUSE); - event.at0 = kMenuEventScrollDown; - } - else - return CGameMenuItem::MouseEvent(event); - return event.at0 != kMenuEventNone; -} - -CGameMenuItemZCycle::CGameMenuItemZCycle() -{ - m_pzText = NULL; - m_nFocus = 0; - m_nItems = 0; - m_pCallback = NULL; - m_pCallbackSelect = NULL; - m_pMenuSelect = NULL; - m_pItemSelectTitle = NULL; - m_pItemSelect = NULL; - m_nMenuSelectReturn = -1; -} - -CGameMenuItemZCycle::CGameMenuItemZCycle(const char *a1, int a2, int a3, int a4, int a5, int a6, void(*a7)(CGameMenuItemZCycle *), const char **a8, int a9, int a10, bool bMenu, void(*pCallbackSelect)(CGameMenuItemZCycleSelect*)) -{ - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - m_nFocus = 0; - m_nWidth = a5; - m_nAlign = a6; - m_pCallback = a7; - m_pCallbackSelect = pCallbackSelect; - m_nItems = 0; - m_bMenu = bMenu; - m_pMenuSelect = NULL; - m_pItemSelectTitle = NULL; - m_pItemSelect = NULL; - m_nMenuSelectReturn = -1; - SetTextArray(a8, a9, a10); -} - -CGameMenuItemZCycle::~CGameMenuItemZCycle() -{ - m_pzText = NULL; - m_nFocus = 0; - m_nItems = 0; - m_pCallback = NULL; - m_pCallbackSelect = NULL; - m_pMenuSelect = NULL; - m_pItemSelectTitle = NULL; - m_pItemSelect = NULL; - m_nMenuSelectReturn = -1; - memset(m_pzStrings, 0, sizeof(m_pzStrings)); -} - -void CGameMenuItemZCycle::Draw(void) -{ - int width = 0, height = 0; - int shade = bEnable ? 32 : 48; - int pal = bEnable ? 0 : 5; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - int x = m_nX; - int y = m_nY; - - if (m_nMenuSelectReturn != -1) - { - m_nFocus = m_nMenuSelectReturn; - if (m_pCallback) - m_pCallback(this); - m_nMenuSelectReturn = -1; - } - - if (m_pzText) - { - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, &height); - switch (m_nAlign) - { - case 1: - x = m_nX+m_nWidth/2-width/2; - break; - case 2: - x = m_nX+m_nWidth-1-width; - break; - case 0: - default: - break; - } - gMenuTextMgr.DrawText(m_pzText, m_nFont, x, y, shade, pal, false); - } - const char *pzText; - if (!m_nItems) - pzText = "????"; - else - pzText = m_pzStrings[m_nFocus]; - dassert(pzText != NULL); - gMenuTextMgr.GetFontInfo(m_nFont, pzText, &width, NULL); - gMenuTextMgr.DrawText(pzText, m_nFont, m_nX + m_nWidth - 1 - width, y, shade, pal, false); - if (bEnable && MOUSEACTIVECONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousepos, x<<16, y<<16, m_nWidth<<16, height<<16))) - { - if (MOUSEWATCHPOINTCONDITIONAL(!gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_prevmousepos, x<<16, y<<16, m_nWidth<<16, height<<16))) - { - pMenu->SetFocusItem(this); - } - - if (!gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !gGameMenuMgr.MouseOutsideBounds(&gGameMenuMgr.m_mousedownpos, x<<16, y<<16, m_nWidth<<16, height<<16)) - { - pMenu->SetFocusItem(this); - - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } - } -} - -bool CGameMenuItemZCycle::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventEnter: - if (m_bMenu) - { - if (m_pMenuSelect) - { - delete m_pMenuSelect; - m_pMenuSelect = NULL; - } - if (m_pItemSelectTitle) - { - delete m_pItemSelectTitle; - m_pItemSelectTitle = NULL; - } - if (m_pItemSelect) - { - delete m_pItemSelect; - m_pItemSelect = NULL; - } - m_pMenuSelect = new CGameMenu(); - dassert(m_pMenuSelect != NULL); - strncpy(m_zTitle, m_pzText, kMaxTitleLength); - int l = strlen(m_zTitle); - if (l > 0 && m_zTitle[l-1] == ':') - l--; - m_zTitle[l] = 0; - m_pItemSelectTitle = new CGameMenuItemTitle(m_zTitle, 1, 160, 20, 2038); - dassert(m_pItemSelectTitle != NULL); - m_pItemSelect = new CGameMenuItemZCycleSelect("", 3, 100, 40, 100, 16, m_nItems, m_pzStrings, &m_nMenuSelectReturn, m_pCallbackSelect); - dassert(m_pItemSelect != NULL); - m_pMenuSelect->Add(m_pItemSelectTitle, false); - m_pMenuSelect->Add(m_pItemSelect, true); - m_pMenuSelect->Add(&itemBloodQAV, false); - gGameMenuMgr.Push(m_pMenuSelect, -1); - return false; - } - fallthrough__; - case kMenuEventRight: - case kMenuEventSpace: - Next(); - if (m_pCallback) - m_pCallback(this); - return false; - case kMenuEventLeft: - Prev(); - if (m_pCallback) - m_pCallback(this); - return false; - case kMenuEventDeInit: - if (m_pMenuSelect) - { - delete m_pMenuSelect; - m_pMenuSelect = NULL; - } - if (m_pItemSelectTitle) - { - delete m_pItemSelectTitle; - m_pItemSelectTitle = NULL; - } - if (m_pItemSelect) - { - delete m_pItemSelect; - m_pItemSelect = NULL; - } - return false; - } - return CGameMenuItem::Event(event); -} - -void CGameMenuItemZCycle::Add(const char *pItem, bool active) -{ - dassert(pItem != NULL); - dassert(m_nItems < kMaxGameCycleItems); - m_pzStrings[m_nItems] = pItem; - if (active) - m_nFocus = m_nItems; - m_nItems++; -} - -void CGameMenuItemZCycle::Next(void) -{ - if (m_nItems > 0) - { - m_nFocus++; - if (m_nFocus >= m_nItems) - m_nFocus = 0; - } -} - -void CGameMenuItemZCycle::Prev(void) -{ - if (m_nItems > 0) - { - m_nFocus--; - if (m_nFocus < 0) - m_nFocus += m_nItems; - } -} - -void CGameMenuItemZCycle::Clear(void) -{ - m_nItems = m_nFocus = 0; - memset(m_pzStrings, 0, sizeof(m_pzStrings)); -} - -void CGameMenuItemZCycle::SetTextArray(const char **pTextArray, int nTextPtrCount, int nIndex) -{ - Clear(); - dassert(nTextPtrCount <= kMaxGameCycleItems); - for (int i = 0; i < nTextPtrCount; i++) - Add(pTextArray[i], false); - SetTextIndex(nIndex); -} - -void CGameMenuItemZCycle::SetTextIndex(int nIndex) -{ - m_nFocus = ClipRange(nIndex, 0, m_nItems); -} - -CGameMenuItemYesNoQuit::CGameMenuItemYesNoQuit() -{ - m_pzText = NULL; - m_nRestart = 0; -} - -CGameMenuItemYesNoQuit::CGameMenuItemYesNoQuit(const char *a1, int a2, int a3, int a4, int a5, int a6, int a7) -{ - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; - m_nWidth = a5; - at20 = a6; - m_nRestart = a7; -} - -void CGameMenuItemYesNoQuit::Draw(void) -{ - if (!m_pzText) return; - int shade = 32; - if (pMenu->IsFocusItem(this)) - shade = 32-((int)totalclock&63); - int width; - int x = m_nX; - switch (at20) - { - case 1: - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - x = m_nX+m_nWidth/2-width/2; - break; - case 2: - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - x = m_nX+m_nWidth-1-width; - break; - case 0: - default: - break; - } - gMenuTextMgr.DrawText(m_pzText, m_nFont, x, m_nY, shade, 0, true); - - if (bEnable && !gGameMenuMgr.m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED) - { - pMenu->SetFocusItem(this); - - CGameMenuEvent event = { kMenuEventEnter, 0 }; - - gGameMenuMgr.m_mousecaught = 1; - - if (Event(event)) - gGameMenuMgr.PostPop(); - } -} - -extern void Restart(CGameMenuItemChain *pItem); -extern void Quit(CGameMenuItemChain *pItem); - -bool CGameMenuItemYesNoQuit::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventKey: - if (event.at2 == sc_Y) - { - if (m_nRestart) - Restart(NULL); - else - Quit(NULL); - } - else if (event.at2 == sc_N) - gGameMenuMgr.Pop(); - return false; - case kMenuEventEnter: - if (m_nRestart) - Restart(NULL); - else - Quit(NULL); - return false; - } - return CGameMenuItem::Event(event); -} - -CGameMenuItemPicCycle::CGameMenuItemPicCycle() -{ - m_pzText = NULL; - at24 = 0; - m_nItems = 0; - atb0 = 0; - at2c = 0; - atb4 = 0; -} - -CGameMenuItemPicCycle::CGameMenuItemPicCycle(int a1, int a2, void(*a3)(CGameMenuItemPicCycle *), int *a4, int a5, int a6) -{ - m_nWidth = 0; - at24 = 0; - m_nItems = 0; - m_nX = a1; - m_nY = a2; - atb0 = a3; - atb4 = 0; - SetPicArray(a4, a5, a6); -} - -void CGameMenuItemPicCycle::Draw(void) -{ - videoSetViewableArea(0, 0, xdim - 1, ydim - 1); - if (atb4) - rotatesprite(0, 0, 65536, 0, atb4, 0, 0, 82, 0, 0, xdim - 1, ydim - 1); - if (at30[at24]) - rotatesprite(0, 0, 65536, 0, at30[at24], 0, 0, 82, 0, 0, xdim - 1, ydim - 1); -} - -bool CGameMenuItemPicCycle::Event(CGameMenuEvent &event) -{ - switch (event.at0) - { - case kMenuEventRight: - case kMenuEventEnter: - case kMenuEventSpace: - Next(); - if (atb0) - atb0(this); - return false; - case kMenuEventLeft: - Prev(); - if (atb0) - atb0(this); - return false; - } - return CGameMenuItem::Event(event); -} - -void CGameMenuItemPicCycle::Add(int nItem, bool active) -{ - dassert(m_nItems < kMaxPicCycleItems); - at30[m_nItems] = nItem; - if (active) - at24 = m_nItems; - m_nItems++; -} - -void CGameMenuItemPicCycle::Next(void) -{ - if (m_nItems > 0) - { - at24++; - if (at24 >= m_nItems) - at24 = 0; - } -} - -void CGameMenuItemPicCycle::Prev(void) -{ - if (m_nItems > 0) - { - at24--; - if (at24 < 0) - at24 += m_nItems; - } -} - -void CGameMenuItemPicCycle::Clear(void) -{ - m_nItems = at24 = 0; - memset(at30, 0, sizeof(at30)); - at2c = 0; -} - -void CGameMenuItemPicCycle::SetPicArray(int *pArray, int nTileCount, int nIndex) -{ - Clear(); - at2c = 0; - dassert(nTileCount <= kMaxPicCycleItems); - for (int i = 0; i < nTileCount; i++) - Add(pArray[i], false); - SetPicIndex(nIndex); -} - -void CGameMenuItemPicCycle::SetPicIndex(int nIndex) -{ - at24 = ClipRange(nIndex, 0, m_nItems); -} - -CGameMenuItemPassword::CGameMenuItemPassword() -{ - at37 = 0; - m_pzText = NULL; - at36 = 0; - at32 = 0; - at5b = 0; -} - -CGameMenuItemPassword::CGameMenuItemPassword(const char *a1, int a2, int a3, int a4) -{ - at37 = 0; - m_nWidth = 0; - at36 = 0; - at32 = 0; - at5b = 0; - m_pzText = a1; - m_nFont = a2; - m_nX = a3; - m_nY = a4; -} - -const char *kCheckPasswordMsg = "ENTER PASSWORD: "; -const char *kOldPasswordMsg = "ENTER OLD PASSWORD: "; -const char *kNewPasswordMsg = "ENTER NEW PASSWORD: "; -const char *kInvalidPasswordMsg = "INVALID PASSWORD."; - -void CGameMenuItemPassword::Draw(void) -{ - bool focus = pMenu->IsFocusItem(this); - int shade = 32; - int shadef = 32-((int)totalclock&63); - int width; - switch (at37) - { - case 1: - case 2: - case 3: - switch (at37) - { - case 1: - strcpy(at3b, kCheckPasswordMsg); - break; - case 2: - strcpy(at3b, kOldPasswordMsg); - break; - case 3: - strcpy(at3b, kNewPasswordMsg); - break; - } - for (int i = 0; i < at32; i++) - strcat(at3b, "*"); - strcat(at3b, "_"); - gMenuTextMgr.GetFontInfo(m_nFont, at3b, &width, NULL); - gMenuTextMgr.DrawText(at3b, m_nFont, m_nX-width/2, m_nY+20, shadef, 0, false); - shadef = 32; - break; - case 4: - if (((int)totalclock - at5b) & 32) - { - gMenuTextMgr.GetFontInfo(m_nFont, kInvalidPasswordMsg, &width, NULL); - gMenuTextMgr.DrawText(kInvalidPasswordMsg, m_nFont, m_nX - width / 2, m_nY + 20, shade, 0, false); - } - if (at5b && totalclock-at5b > 256) - { - at5b = 0; - at37 = 0; - } - break; - } - gMenuTextMgr.GetFontInfo(m_nFont, m_pzText, &width, NULL); - gMenuTextMgr.DrawText(m_pzText, m_nFont, m_nX-width/2, m_nY, focus ? shadef : shade, 0, false); -} - -bool CGameMenuItemPassword::Event(CGameMenuEvent &event) -{ - switch (at37) - { - case 0: - case 4: - if (event.at0 == kMenuEventEnter) - { - at29[0] = 0; - if (strcmp(at20, "")) - at37 = 2; - else - at37 = 3; - return false; - } - return CGameMenuItem::Event(event); - case 1: - case 2: - case 3: - switch (event.at0) - { - case kMenuEventEnter: - switch (at37) - { - case 1: - at36 = strcmp(at20,at29) == 0; - if (at36) - at37 = 0; - else - at37 = 4; - if (!at36) - { - at5b = (int)totalclock; - pMenu->FocusPrevItem(); - } - else - { - at5f->at20 = 0; - at5f->Draw(); - gbAdultContent = false; - // NUKE-TODO: - //CONFIG_WriteAdultMode(); - pMenu->FocusPrevItem(); - } - return false; - case 2: - at36 = strcmp(at20,at29) == 0; - if (at36) - at37 = 0; - else - at37 = 4; - if (at36) - { - strcpy(at20, ""); - strcpy(gzAdultPassword, ""); - // NUKE-TODO: - //CONFIG_WriteAdultMode(); - at37 = 0; - } - else - at5b = (int)totalclock; - return false; - case 3: - strcpy(at20, at29); - strcpy(at20, gzAdultPassword); - strcpy(gzAdultPassword, ""); - // NUKE-TODO: - //CONFIG_WriteAdultMode(); - at37 = 0; - return false; - } - break; - case kMenuEventEscape: - at37 = 0; - Draw(); - return false; - case kMenuEventKey: - if (at32 < 8) - { - char key = Btoupper(g_keyAsciiTable[event.at2]); - if (isalnum(key) || ispunct(key) || isspace(key)) - { - at29[at32++] = key; - at29[at32] = 0; - } - } - return false; - case kMenuEventBackSpace: - if (at32 > 0) - at29[--at32] = 0; - return false; - case kMenuEventLeft: - case kMenuEventRight: - case kMenuEventSpace: - return false; - } - } - return CGameMenuItem::Event(event); -} - -bool GameInterface::mouseInactiveConditional(bool condition) -{ - return MOUSEINACTIVECONDITIONAL(condition); -} END_BLD_NS diff --git a/source/blood/src/gamemenu.h b/source/blood/src/gamemenu.h index f1cad59af..909d714c2 100644 --- a/source/blood/src/gamemenu.h +++ b/source/blood/src/gamemenu.h @@ -31,464 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -#define M_MOUSETIMEOUT 210 - -#define kMaxGameMenuItems 128 -#define kMaxGameCycleItems 128 -#define kMaxPicCycleItems 128 -#define kMaxTitleLength 32 - -// alpha increments of 3 --> 255 / 3 = 85 --> round up to power of 2 --> 128 --> divide by 2 --> 64 alphatabs required -// use 16 anyway :P -#define MOUSEUSEALPHA (videoGetRenderMode() != REND_CLASSIC || numalphatabs >= 15) -#define MOUSEALPHA (MOUSEUSEALPHA ? clamp(((int)totalclock - gGameMenuMgr.m_mouselastactivity - 90)*3, 0, 255) : 0) -#define CURSORALPHA (MOUSEUSEALPHA ? clamp(((int)totalclock - gGameMenuMgr.m_mouselastactivity - 90)*2 + (255/3), (255/3), 255) : 255/3) -#define MOUSEACTIVECONDITION ((int)totalclock - gGameMenuMgr.m_mouselastactivity < M_MOUSETIMEOUT) -#define MOUSEACTIVECONDITIONAL(condition) (MOUSEACTIVECONDITION && (condition)) -#define MOUSEINACTIVECONDITIONAL(condition) (!MOUSEACTIVECONDITION && (condition)) -#define MOUSEWATCHPOINTCONDITIONAL(condition) ((condition) || gGameMenuMgr.m_mousewake_watchpoint || gGameMenuMgr.m_menuchange_watchpoint == 3) - -enum { - kMenuEventNone = 0, - kMenuEventKey = 1, - kMenuEventUp = 2, - kMenuEventDown = 3, - kMenuEventLeft = 4, - kMenuEventRight = 5, - kMenuEventEnter = 6, - kMenuEventEscape = 7, - kMenuEventSpace = 8, - kMenuEventBackSpace = 9, - kMenuEventDelete = 10, - kMenuEventScrollUp = 11, - kMenuEventScrollDown = 12, - - - kMenuEventInit = 0x8000, - kMenuEventDeInit = 0x8001 -}; - -enum { - kMenuSliderNone = 0, - kMenuSliderValue, - kMenuSliderPercent, - kMenuSliderQ16 -}; - -struct CGameMenuEvent { - unsigned short at0; - char at2; -}; - -// NUKE-TODO: -#ifdef DrawText -#undef DrawText -#endif - -class CMenuTextMgr -{ -public: - int at0; - CMenuTextMgr(); - void DrawText(const char *pString, int nFont, int x, int y, int nShade, int nPalette, bool shadow ); - void GetFontInfo(int nFont, const char *pString, int *pXSize, int *pYSize); -}; - -class CGameMenu; - -class CGameMenuItem { -public: - CGameMenu *pMenu; - const char* m_pzText; - int m_nFont; - int m_nX; - int m_nY; - int m_nWidth; - void (*pPreDrawCallback)(CGameMenuItem *pItem); - //int nFlags; - unsigned int bCanSelect : 1; - unsigned int bEnable : 1; - unsigned int bNoDraw : 1; - CGameMenuItem(); - virtual ~CGameMenuItem(); - virtual void Draw(void) = 0; - virtual bool Event(CGameMenuEvent &); - virtual bool MouseEvent(CGameMenuEvent &); -}; - -class CGameMenuItemText : public CGameMenuItem -{ -public: - int at20; - CGameMenuItemText(); - CGameMenuItemText(const char *, int, int, int, int); - virtual void Draw(void); - //virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemTitle : public CGameMenuItem -{ -public: - int at20; - CGameMenuItemTitle(); - CGameMenuItemTitle(const char *, int, int, int, int); - virtual void Draw(void); - //virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemZBool : public CGameMenuItem -{ -public: - bool at20; - const char *at21; - const char *at25; - void (*at29)(CGameMenuItemZBool *); - CGameMenuItemZBool(); - CGameMenuItemZBool(const char *,int,int,int,int,bool,void (*)(CGameMenuItemZBool *),const char *,const char *); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemChain : public CGameMenuItem -{ -public: - int at20; - CGameMenu *at24; - int at28; - void(*at2c)(CGameMenuItemChain *); - int at30; - CGameMenuItemChain(); - CGameMenuItemChain(const char *, int, int, int, int, int, CGameMenu *, int, void(*)(CGameMenuItemChain *), int); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItem7EA1C : public CGameMenuItem -{ -public: - int at20; // text align - CGameMenu *at24; - int at28; - void(*at2c)(CGameMenuItem7EA1C *); - int at30; - IniFile *at34; - char at38[16]; - char at48[16]; - CGameMenuItem7EA1C(); - CGameMenuItem7EA1C(const char *a1, int a2, int a3, int a4, int a5, const char *a6, const char *a7, int a8, int a9, void(*a10)(CGameMenuItem7EA1C *), int a11); - void Setup(void); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItem7EE34 : public CGameMenuItem -{ -public: - int at20; - int at24; - CGameMenu *at28; - CGameMenu *at2c; - CGameMenuItem7EE34(); - CGameMenuItem7EE34(const char *a1, int a2, int a3, int a4, int a5, int a6); - void Setup(void); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemChain7F2F0 : public CGameMenuItemChain -{ -public: - int at34; - CGameMenuItemChain7F2F0(); - CGameMenuItemChain7F2F0(char *a1, int a2, int a3, int a4, int a5, int a6, CGameMenu *a7, int a8, void(*a9)(CGameMenuItemChain *), int a10); - //virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemBitmap : public CGameMenuItem -{ -public: - int at20; - CGameMenuItemBitmap(); - CGameMenuItemBitmap(const char *, int, int, int, int); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemBitmapLS : public CGameMenuItemBitmap -{ -public: - int at24; - int at28; - CGameMenuItemBitmapLS(); - CGameMenuItemBitmapLS(const char *, int, int, int, int); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemKeyList : public CGameMenuItem -{ -public: - void(*pCallback)(CGameMenuItemKeyList *); - int at24; - int nRows; - int nTopDelta; - int nFocus; - int nGameFuncs; - bool bScan; - CGameMenuItemKeyList(); - CGameMenuItemKeyList(const char * a1, int a2, int a3, int a4, int a5, int a6, int a7, void(*a8)(CGameMenuItemKeyList *)); - void Scan(void); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); - virtual bool MouseEvent(CGameMenuEvent &); -}; - -class CGameMenuItemSlider : public CGameMenuItem -{ -public: - int *pValue; - int nValue; - int nRangeLow; - int nRangeHigh; - int nStep; - void(*pCallback)(CGameMenuItemSlider *); - int nSliderTile; - int nCursorTile; - int nShowValue; - CGameMenuItemSlider(); - CGameMenuItemSlider(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, int _nValue, int _nRangeLow, int _nRangeHigh, int _nStep, void(*_pCallback)(CGameMenuItemSlider *), int _nSliderTile, int _nCursorTile, int _nShowValue = kMenuSliderNone); - CGameMenuItemSlider(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, int *pnValue, int _nRangeLow, int _nRangeHigh, int _nStep, void(*_pCallback)(CGameMenuItemSlider *), int _nSliderTile, int _nCursorTile, int _nShowValue = kMenuSliderNone); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); - virtual bool MouseEvent(CGameMenuEvent &); -}; - -class CGameMenuItemSliderFloat : public CGameMenuItem -{ -public: - float *pValue; - float fValue; - float fRangeLow; - float fRangeHigh; - float fStep; - void(*pCallback)(CGameMenuItemSliderFloat *); - int nSliderTile; - int nCursorTile; - int nShowValue; - CGameMenuItemSliderFloat(); - CGameMenuItemSliderFloat(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, float _fValue, float _fRangeLow, float _fRangeHigh, float _fStep, void(*_pCallback)(CGameMenuItemSliderFloat *), int _nSliderTile, int _nCursorTile, int _nShowValue = kMenuSliderNone); - CGameMenuItemSliderFloat(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, float *pnValue, float _fRangeLow, float _fRangeHigh, float _fStep, void(*_pCallback)(CGameMenuItemSliderFloat *), int _nSliderTile, int _nCursorTile, int _nShowValue = kMenuSliderNone); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemZEdit : public CGameMenuItem -{ -public: - char *at20; - int at24; - int at28; - void(*at2c)(CGameMenuItemZEdit *, CGameMenuEvent *); - char at30; - char at31; - char at32; - CGameMenuItemZEdit(); - CGameMenuItemZEdit(const char *, int, int, int, int, char *, int, char, void(*)(CGameMenuItemZEdit *, CGameMenuEvent *), int); - void AddChar(char); - void BackChar(void); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemZEditBitmap : public CGameMenuItem -{ -public: - char *at20; - int at24; - int at28; - CGameMenuItemBitmapLS *at2c; - void(*at30)(CGameMenuItemZEditBitmap *, CGameMenuEvent *); - char bScan; - char at35; - char at36; - char at37; - CGameMenuItemZEditBitmap(); - CGameMenuItemZEditBitmap(char *, int, int, int, int, char *, int, char, void(*)(CGameMenuItemZEditBitmap *, CGameMenuEvent *), int); - void AddChar(char); - void BackChar(void); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemQAV : public CGameMenuItem -{ -public: - const char *at20; - DICTNODE *at24; - QAV *at28; - int at2c; - int at30; - bool bWideScreen; - bool bClearBackground; - CGameMenuItemQAV(); - CGameMenuItemQAV(const char *, int, int, int, const char *, bool widescreen = false, bool clearbackground = false); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); - void Reset(void); -}; - -class CGameMenuItemZCycleSelect : public CGameMenuItem -{ -public: - void(*m_pCallback)(CGameMenuItemZCycleSelect *); - int m_nRows; - int m_nTopDelta; - int m_nFocus; - int m_nItems; - int *m_pReturn; - const char **m_pzStrings; - CGameMenuItemZCycleSelect(); - CGameMenuItemZCycleSelect(const char *pzText, int nFont, int nX, int nY, int nWidth, int nRows, int nItems, const char **pzStrings, int *pReturn, void(*pCallback)(CGameMenuItemZCycleSelect *)); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); - virtual bool MouseEvent(CGameMenuEvent &); -}; - - -class CGameMenuItemZCycle : public CGameMenuItem -{ -public: - int m_nItems; - int m_nFocus; - int m_nAlign; - const char *m_pzStrings[kMaxGameCycleItems]; - char m_zTitle[kMaxTitleLength]; - void(*m_pCallback)(CGameMenuItemZCycle *); - void(*m_pCallbackSelect)(CGameMenuItemZCycleSelect *); - bool m_bMenu; - int m_nMenuSelectReturn; - CGameMenu *m_pMenuSelect; - CGameMenuItemTitle *m_pItemSelectTitle; - CGameMenuItemZCycleSelect *m_pItemSelect; - CGameMenuItemZCycle(); - CGameMenuItemZCycle(const char *, int, int, int, int, int, void(*)(CGameMenuItemZCycle *), const char **, int, int, bool = false, void(*)(CGameMenuItemZCycleSelect*) = NULL); - ~CGameMenuItemZCycle(); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); - void Add(const char *, bool); - void Next(void); - void Prev(void); - void Clear(void); - void SetTextArray(const char **, int, int); - void SetTextIndex(int); -}; - -class CGameMenuItemYesNoQuit : public CGameMenuItem -{ -public: - int at20; - int m_nRestart; - CGameMenuItemYesNoQuit(); - CGameMenuItemYesNoQuit(const char *, int, int, int, int, int, int); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - -class CGameMenuItemPicCycle : public CGameMenuItem -{ -public: - int m_nItems; - int at24; - int at28; - int at2c; - int at30[kMaxPicCycleItems]; - void(*atb0)(CGameMenuItemPicCycle *); - int atb4; - CGameMenuItemPicCycle(); - CGameMenuItemPicCycle(int, int, void(*)(CGameMenuItemPicCycle *), int *, int, int); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); - void Add(int, bool); - void Next(void); - void Prev(void); - void Clear(void); - void SetPicArray(int *, int, int); - void SetPicIndex(int); -}; - -class CGameMenuItemPassword : public CGameMenuItem -{ -public: - char at20[9]; - char at29[9]; - int at32; - char at36; - int at37; - char at3b[32]; - int at5b; - CGameMenuItemZBool *at5f; - CGameMenuItemPassword(); - CGameMenuItemPassword(const char *, int, int, int); - virtual void Draw(void); - virtual bool Event(CGameMenuEvent &); -}; - - -class CGameMenu -{ -public: - int m_nItems; - int m_nFocus; - int at8; - char atc; - CGameMenuItem *pItemList[kMaxGameMenuItems]; // atd - CGameMenu(); - CGameMenu(int); - ~CGameMenu(); - void InitializeItems(CGameMenuEvent &event); - void Draw(void); - bool Event(CGameMenuEvent &event); - void Add(CGameMenuItem *pItem, bool active); - void SetFocusItem(int nItem); - void SetFocusItem(CGameMenuItem *Item); - bool CanSelectItem(int nItem); - void FocusPrevItem(void); - void FocusNextItem(void); - bool IsFocusItem(CGameMenuItem *pItem); - bool MouseEvent(CGameMenuEvent &event); -}; - -class CGameMenuMgr -{ -public: - static bool m_bInitialized; - static bool m_bActive; - static bool m_bScanning; - CGameMenu *pTempMenu; - CGameMenu *pActiveMenu; - CGameMenu *pMenuStack[8]; - int nMenuPointer; - int32_t m_mouselastactivity; - int32_t m_mousewake_watchpoint, m_menuchange_watchpoint; - int32_t m_mousecaught; - vec2_t m_prevmousepos, m_mousepos, m_mousedownpos; - bool m_postPop; - CGameMenuMgr(); - ~CGameMenuMgr(); - void InitializeMenu(void); - void DeInitializeMenu(void); - bool Push(CGameMenu *pMenu, int data); - void Pop(void); - void PostPop(void); - void Draw(void); - void Clear(void); - void Process(void); - void Deactivate(void); - bool MouseOutsideBounds(vec2_t const * const pos, const int32_t x, const int32_t y, const int32_t width, const int32_t height); -}; - -extern CMenuTextMgr gMenuTextMgr; -extern CGameMenuMgr gGameMenuMgr; +void drawLoadingScreen(void); +void UpdateNetworkMenus(void); END_BLD_NS diff --git a/source/blood/src/globals.cpp b/source/blood/src/globals.cpp index a9d70643a..bbfd71188 100644 --- a/source/blood/src/globals.cpp +++ b/source/blood/src/globals.cpp @@ -62,7 +62,6 @@ void _consoleSysMsg(const char* pzFormat, ...) { va_list args; va_start(args, pzFormat); vsprintf(buffer, pzFormat, args); - initprintf("%s(%i): %s\n", _module, _line, buffer); OSD_Printf(OSDTEXT_RED "%s(%i): %s\n", _module, _line, buffer); } diff --git a/source/blood/src/inifile.cpp b/source/blood/src/inifile.cpp index b9263efe6..78fd149ec 100644 --- a/source/blood/src/inifile.cpp +++ b/source/blood/src/inifile.cpp @@ -130,7 +130,7 @@ void IniFile::Load() curNode = &head; - auto fp = kopenFileReader(fileName, 0); + auto fp = fileSystem.OpenFileReader(fileName, 0); if (fp.isOpen()) { int nSize = fp.GetLength(); diff --git a/source/blood/src/levels.cpp b/source/blood/src/levels.cpp index 55a1819d2..b778153b4 100644 --- a/source/blood/src/levels.cpp +++ b/source/blood/src/levels.cpp @@ -43,13 +43,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sfx.h" #include "view.h" #include "eventq.h" +#include "menu/menu.h" BEGIN_BLD_NS GAMEOPTIONS gGameOptions; GAMEOPTIONS gSingleGameOptions = { - 0, 2, 0, 0, "", "", 2, "", "", 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3600, 1800, 1800, 7200 + 0, 2, 0, 0, "", 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3600, 1800, 1800, 7200 }; EPISODEINFO gEpisodeInfo[kMaxEpisodes+1]; @@ -69,7 +70,7 @@ IniFile *BloodINI; void levelInitINI(const char *pzIni) { - if (!testkopen(pzIni, 0)) + if (!fileSystem.FileExists(pzIni)) ThrowError("Initialization: %s does not exist", pzIni); BloodINI = new IniFile(pzIni); Bstrncpy(BloodIniFile, pzIni, BMAX_PATH); @@ -87,7 +88,7 @@ void levelOverrideINI(const char *pzIni) void levelPlayIntroScene(int nEpisode) { gGameOptions.uGameFlags &= ~4; - sndStopSong(); + Mus_Stop(); sndKillAllSounds(); sfxKillAllSounds(); ambKillAll(); @@ -103,7 +104,7 @@ void levelPlayIntroScene(int nEpisode) void levelPlayEndScene(int nEpisode) { gGameOptions.uGameFlags &= ~8; - sndStopSong(); + Mus_Stop(); sndKillAllSounds(); sfxKillAllSounds(); ambKillAll(); @@ -145,48 +146,48 @@ void CheckKeyAbend(const char *pzSection, const char *pzKey) ThrowError("Key %s expected in section [%s] of BLOOD.INI", pzKey, pzSection); } -LEVELINFO * levelGetInfoPtr(int nEpisode, int nLevel) +MapRecord * levelGetInfoPtr(int nEpisode, int nLevel) { dassert(nEpisode >= 0 && nEpisode < gEpisodeCount); EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[nEpisode]; dassert(nLevel >= 0 && nLevel < pEpisodeInfo->nLevels); - return &pEpisodeInfo->at28[nLevel]; + return &pEpisodeInfo->levels[nLevel]; } -char * levelGetFilename(int nEpisode, int nLevel) +const char * levelGetFilename(int nEpisode, int nLevel) { dassert(nEpisode >= 0 && nEpisode < gEpisodeCount); EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[nEpisode]; dassert(nLevel >= 0 && nLevel < pEpisodeInfo->nLevels); - return pEpisodeInfo->at28[nLevel].at0; + return pEpisodeInfo->levels[nLevel].labelName; } -char * levelGetMessage(int nMessage) +const char * levelGetMessage(int nMessage) { int nEpisode = gGameOptions.nEpisode; int nLevel = gGameOptions.nLevel; dassert(nMessage < kMaxMessages); - char *pMessage = gEpisodeInfo[nEpisode].at28[nLevel].atec[nMessage]; + const char *pMessage = gEpisodeInfo[nEpisode].levels[nLevel].GetMessage(nMessage); if (*pMessage == 0) return NULL; return pMessage; } -char * levelGetTitle(void) +const char * levelGetTitle(void) { int nEpisode = gGameOptions.nEpisode; int nLevel = gGameOptions.nLevel; - char *pTitle = gEpisodeInfo[nEpisode].at28[nLevel].at90; + const char *pTitle = gEpisodeInfo[nEpisode].levels[nLevel].DisplayName(); if (*pTitle == 0) return NULL; return pTitle; } -char * levelGetAuthor(void) +const char * levelGetAuthor(void) { int nEpisode = gGameOptions.nEpisode; int nLevel = gGameOptions.nLevel; - char *pAuthor = gEpisodeInfo[nEpisode].at28[nLevel].atb0; + const char *pAuthor = gEpisodeInfo[nEpisode].levels[nLevel].author; if (*pAuthor == 0) return NULL; return pAuthor; @@ -196,39 +197,37 @@ void levelSetupOptions(int nEpisode, int nLevel) { gGameOptions.nEpisode = nEpisode; gGameOptions.nLevel = nLevel; - strcpy(gGameOptions.zLevelName, gEpisodeInfo[nEpisode].at28[nLevel].at0); + strcpy(gGameOptions.zLevelName, gEpisodeInfo[nEpisode].levels[nLevel].labelName); gGameOptions.uMapCRC = dbReadMapCRC(gGameOptions.zLevelName); - // strcpy(gGameOptions.zLevelSong, gEpisodeInfo[nEpisode].at28[nLevel].atd0); - gGameOptions.nTrackNumber = gEpisodeInfo[nEpisode].at28[nLevel].ate0; + gGameOptions.nTrackNumber = gEpisodeInfo[nEpisode].levels[nLevel].cdSongId; } -void levelLoadMapInfo(IniFile *pIni, LEVELINFO *pLevelInfo, const char *pzSection) +void levelLoadMapInfo(IniFile *pIni, MapRecord *pLevelInfo, const char *pzSection, int epinum, int mapnum) { char buffer[16]; - strncpy(pLevelInfo->at90, pIni->GetKeyString(pzSection, "Title", pLevelInfo->at0), 31); - strncpy(pLevelInfo->atb0, pIni->GetKeyString(pzSection, "Author", ""), 31); - strncpy(pLevelInfo->atd0, pIni->GetKeyString(pzSection, "Song", ""), BMAX_PATH); - pLevelInfo->ate0 = pIni->GetKeyInt(pzSection, "Track", -1); - pLevelInfo->ate4 = pIni->GetKeyInt(pzSection, "EndingA", -1); - pLevelInfo->ate8 = pIni->GetKeyInt(pzSection, "EndingB", -1); - pLevelInfo->at8ec = pIni->GetKeyInt(pzSection, "Fog", -0); - pLevelInfo->at8ed = pIni->GetKeyInt(pzSection, "Weather", -0); + pLevelInfo->SetName(pIni->GetKeyString(pzSection, "Title", pLevelInfo->labelName)); + pLevelInfo->author = pIni->GetKeyString(pzSection, "Author", ""); + pLevelInfo->music.Format("%s.%s", pIni->GetKeyString(pzSection, "Song", ""), ".mid"); + pLevelInfo->cdSongId = pIni->GetKeyInt(pzSection, "Track", -1); + pLevelInfo->nextLevel = pIni->GetKeyInt(pzSection, "EndingA", -1); //if (pLevelInfo->nextLevel >= 0) pLevelInfo->nextLevel +epinum * kMaxLevels; + pLevelInfo->nextSecret = pIni->GetKeyInt(pzSection, "EndingB", -1); //if (pLevelInfo->nextSecret >= 0) pLevelInfo->nextSecret + epinum * kMaxLevels; + pLevelInfo->fog = pIni->GetKeyInt(pzSection, "Fog", -0); + pLevelInfo->weather = pIni->GetKeyInt(pzSection, "Weather", -0); + pLevelInfo->messageStart = 1024 + ((epinum * kMaxLevels) + mapnum) * kMaxMessages; for (int i = 0; i < kMaxMessages; i++) { sprintf(buffer, "Message%d", i+1); - strncpy(pLevelInfo->atec[i], pIni->GetKeyString(pzSection, buffer, ""), 63); + quoteMgr.InitializeQuote(pLevelInfo->messageStart + i, pIni->GetKeyString(pzSection, buffer, ""), true); } } -extern void MenuSetupEpisodeInfo(void); - void levelLoadDefaults(void) { char buffer[64]; char buffer2[16]; levelInitINI(G_ConFile()); // This doubles for the INI in the global code. memset(gEpisodeInfo, 0, sizeof(gEpisodeInfo)); - strncpy(gEpisodeInfo[MUS_INTRO/kMaxLevels].at28[MUS_INTRO%kMaxLevels].atd0, "PESTIS", BMAX_PATH); + quoteMgr.InitializeQuote(MUS_INTRO, "PESTIS.MID"); int i; for (i = 0; i < kMaxEpisodes; i++) { @@ -236,7 +235,8 @@ void levelLoadDefaults(void) if (!BloodINI->SectionExists(buffer)) break; EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[i]; - strncpy(pEpisodeInfo->at0, BloodINI->GetKeyString(buffer, "Title", buffer), 31); + auto ep_str = BloodINI->GetKeyString(buffer, "Title", buffer); + gVolumeNames[i] = ep_str; // only keep one table for the names. Todo: Consolidate this across games. strncpy(pEpisodeInfo->at8f08, BloodINI->GetKeyString(buffer, "CutSceneA", ""), BMAX_PATH); pEpisodeInfo->at9028 = BloodINI->GetKeyInt(buffer, "CutWavA", -1); if (pEpisodeInfo->at9028 == 0) @@ -254,22 +254,23 @@ void levelLoadDefaults(void) pEpisodeInfo->cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0); if (pEpisodeInfo->cutALevel > 0) pEpisodeInfo->cutALevel--; + pEpisodeInfo->levels = mapList + i * kMaxLevels; int j; for (j = 0; j < kMaxLevels; j++) { - LEVELINFO *pLevelInfo = &pEpisodeInfo->at28[j]; + auto pLevelInfo = &pEpisodeInfo->levels[j]; sprintf(buffer2, "Map%d", j+1); if (!BloodINI->KeyExists(buffer, buffer2)) break; const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL); CheckSectionAbend(pMap); - strncpy(pLevelInfo->at0, pMap, BMAX_PATH); - levelLoadMapInfo(BloodINI, pLevelInfo, pMap); + pLevelInfo->labelName = pMap; + pLevelInfo->fileName.Format("%s.map", pMap); + levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j); } pEpisodeInfo->nLevels = j; } gEpisodeCount = i; - MenuSetupEpisodeInfo(); } void levelAddUserMap(const char *pzMap) @@ -287,29 +288,28 @@ void levelAddUserMap(const char *pzMap) if (pEpisodeInfo->nLevels == 0) { gEpisodeCount++; - sprintf(pEpisodeInfo->at0, "Episode %d", nEpisode); + gVolumeNames[nEpisode].Format("Episode %d", nEpisode+1); } nLevel = pEpisodeInfo->nLevels++; } - LEVELINFO *pLevelInfo = &pEpisodeInfo->at28[nLevel]; + auto pLevelInfo = &pEpisodeInfo->levels[nLevel]; ChangeExtension(buffer, ""); - strncpy(pLevelInfo->at0, buffer, BMAX_PATH); - levelLoadMapInfo(&UserINI, pLevelInfo, NULL); + pLevelInfo->name = buffer; + levelLoadMapInfo(&UserINI, pLevelInfo, NULL, nEpisode, nLevel); gGameOptions.nEpisode = nEpisode; gGameOptions.nLevel = nLevel; - gGameOptions.uMapCRC = dbReadMapCRC(pLevelInfo->at0); - strcpy(gGameOptions.zLevelName, pLevelInfo->at0); - MenuSetupEpisodeInfo(); + gGameOptions.uMapCRC = dbReadMapCRC(pLevelInfo->name); + strcpy(gGameOptions.zLevelName, pLevelInfo->name); } void levelGetNextLevels(int nEpisode, int nLevel, int *pnEndingA, int *pnEndingB) { dassert(pnEndingA != NULL && pnEndingB != NULL); - LEVELINFO *pLevelInfo = &gEpisodeInfo[nEpisode].at28[nLevel]; - int nEndingA = pLevelInfo->ate4; + auto pLevelInfo = &gEpisodeInfo[nEpisode].levels[nLevel]; + int nEndingA = pLevelInfo->nextLevel; if (nEndingA >= 0) nEndingA--; - int nEndingB = pLevelInfo->ate8; + int nEndingB = pLevelInfo->nextSecret; if (nEndingB >= 0) nEndingB--; *pnEndingA = nEndingA; @@ -399,21 +399,20 @@ int levelGetMusicIdx(const char *str) bool levelTryPlayMusic(int nEpisode, int nLevel, bool bSetLevelSong) { char buffer[BMAX_PATH]; - if (mus_redbook && gEpisodeInfo[nEpisode].at28[nLevel].ate0 > 0) - snprintf(buffer, BMAX_PATH, "blood%02i.ogg", gEpisodeInfo[nEpisode].at28[nLevel].ate0); + if (mus_redbook && gEpisodeInfo[nEpisode].levels[nLevel].cdSongId > 0) + snprintf(buffer, BMAX_PATH, "blood%02i.ogg", gEpisodeInfo[nEpisode].levels[nLevel].cdSongId); else - strncpy(buffer, gEpisodeInfo[nEpisode].at28[nLevel].atd0, BMAX_PATH); - bool bReturn = !!sndPlaySong(gEpisodeInfo[nEpisode].at28[nLevel].atd0, buffer, true); - if (bReturn || bSetLevelSong) - strncpy(gGameOptions.zLevelSong, buffer, BMAX_PATH); - else *gGameOptions.zLevelSong = 0; - return bReturn; + { + strncpy(buffer, gEpisodeInfo[nEpisode].levels[nLevel].music, BMAX_PATH); + } + if (!strchr(buffer, '.')) strcat(buffer, ".mid"); + return !!Mus_Play(gEpisodeInfo[nEpisode].levels[nLevel].labelName, buffer, true); } void levelTryPlayMusicOrNothing(int nEpisode, int nLevel) { if (levelTryPlayMusic(nEpisode, nLevel, true)) - sndStopSong(); + Mus_Stop(); } class LevelsLoadSave : public LoadSave diff --git a/source/blood/src/levels.h b/source/blood/src/levels.h index f331b0d89..1d6aec8e2 100644 --- a/source/blood/src/levels.h +++ b/source/blood/src/levels.h @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #pragma once #include "common_game.h" #include "inifile.h" +#include "mapinfo.h" BEGIN_BLD_NS @@ -39,10 +40,7 @@ struct GAMEOPTIONS { int nEpisode; int nLevel; char zLevelName[BMAX_PATH]; - char zLevelSong[BMAX_PATH]; int nTrackNumber; //at12a; - char szSaveGameName[BMAX_PATH]; - char szUserGameName[BMAX_PATH]; short nSaveGameSlot; int picEntry; unsigned int uMapCRC; @@ -71,27 +69,13 @@ enum { MUS_LOADING = MUS_FIRST_SPECIAL + 1, }; -struct LEVELINFO -{ - char at0[BMAX_PATH]; // Filename - char at90[32]; // Title - char atb0[32]; // Author - char atd0[BMAX_PATH]; // Song; - int ate0; // SongId - int ate4; // EndingA - int ate8; // EndingB - char atec[kMaxMessages][64]; // Messages - char at8ec; // Fog - char at8ed; // Weather -}; // 0x8ee bytes - struct EPISODEINFO { - char at0[32]; + //char at0[32]; removed, so that the global episode name table can be used for consistency int nLevels; unsigned int bloodbath : 1; unsigned int cutALevel : 4; - LEVELINFO at28[kMaxLevels]; + MapRecord* levels; // points into the global table. char at8f08[BMAX_PATH]; char at8f98[BMAX_PATH]; int at9028; @@ -121,13 +105,12 @@ void levelSetupSecret(int nCount); void levelTriggerSecret(int nSecret); void CheckSectionAbend(const char *pzSection); void CheckKeyAbend(const char *pzSection, const char *pzKey); -LEVELINFO * levelGetInfoPtr(int nEpisode, int nLevel); -char * levelGetFilename(int nEpisode, int nLevel); -char * levelGetMessage(int nMessage); -char * levelGetTitle(void); -char * levelGetAuthor(void); +MapRecord * levelGetInfoPtr(int nEpisode, int nLevel); +const char * levelGetFilename(int nEpisode, int nLevel); +const char * levelGetMessage(int nMessage); +const char * levelGetTitle(void); +const char * levelGetAuthor(void); void levelSetupOptions(int nEpisode, int nLevel); -void levelLoadMapInfo(IniFile *pIni, LEVELINFO *pLevelInfo, const char *pzSection); void levelLoadDefaults(void); void levelAddUserMap(const char *pzMap); // EndingA is normal ending, EndingB is secret level diff --git a/source/blood/src/loadsave.cpp b/source/blood/src/loadsave.cpp index 9ea75dd63..a42cf95e3 100644 --- a/source/blood/src/loadsave.cpp +++ b/source/blood/src/loadsave.cpp @@ -35,7 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "globals.h" #include "db.h" #include "messages.h" -#include "menu.h" +#include "gamemenu.h" #include "network.h" #include "loadsave.h" #include "resource.h" @@ -46,13 +46,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sound.h" #include "i_specialpaths.h" #include "view.h" -#include "statistics.h" -#include "secrets.h" #include "savegamehelp.h" +#include "z_music.h" +#include "mapinfo.h" BEGIN_BLD_NS -GAMEOPTIONS gSaveGameOptions[10]; char *gSaveGamePic[10]; unsigned int gSavedOffset = 0; @@ -102,7 +101,7 @@ void LoadSave::Write(void *pData, int nSize) ThrowError("File error #%d writing save file.", errno); } -void LoadSave::LoadGame(char *pzFile) +bool GameInterface::LoadGame(FSaveGameNode* node) { bool demoWasPlayed = gDemo.at1; if (gDemo.at1) @@ -118,20 +117,18 @@ void LoadSave::LoadGame(char *pzFile) memset(sprite, 0, sizeof(spritetype)*kMaxSprites); automapping = 1; } - OpenSaveGameForRead(pzFile); - hLFile = ReadSavegameChunk("snapshot.bld"); - if (!hLFile.isOpen()) - ThrowError("Error loading save file."); - LoadSave *rover = head.next; - while (rover != &head) + OpenSaveGameForRead(node->Filename); + LoadSave::hLFile = ReadSavegameChunk("snapshot.bld"); + if (!LoadSave::hLFile.isOpen()) + return false; + LoadSave *rover = LoadSave::head.next; + while (rover != &LoadSave::head) { rover->Load(); rover = rover->next; } - if (!ReadStatistics() || !SECRET_Load()) // read the rest... - ThrowError("Error loading save file."); - hLFile.Close(); + LoadSave::hLFile.Close(); FinishSavegameRead(); if (!gGameStarted) scrLoadPLUs(); @@ -181,40 +178,41 @@ void LoadSave::LoadGame(char *pzFile) gGameStarted = 1; bVanilla = false; - if (mus_restartonload - || demoWasPlayed - || (gMusicPrevLoadedEpisode != gGameOptions.nEpisode || gMusicPrevLoadedLevel != gGameOptions.nLevel)) - { - levelTryPlayMusic(gGameOptions.nEpisode, gGameOptions.nLevel); - } - gMusicPrevLoadedEpisode = gGameOptions.nEpisode; - gMusicPrevLoadedLevel = gGameOptions.nLevel; + MUS_ResumeSaved(); netBroadcastPlayerInfo(myconnectindex); - //sndPlaySong(gGameOptions.zLevelSong, 1); + return true; } -void LoadSave::SaveGame(char *pzFile) +bool GameInterface::SaveGame(FSaveGameNode* node) { - OpenSaveGameForWrite(pzFile); - hSFile = WriteSavegameChunk("snapshot.bld"); - if (hSFile == NULL) - ThrowError("File error #%d creating save file.", errno); - dword_27AA38 = 0; - dword_27AA40 = 0; - LoadSave *rover = head.next; - while (rover != &head) - { - rover->Save(); - if (dword_27AA38 > dword_27AA40) - dword_27AA40 = dword_27AA38; - dword_27AA38 = 0; - rover = rover->next; - } - SaveStatistics(); - SECRET_Save(); - FinishSavegameWrite(); - hSFile = NULL; + OpenSaveGameForWrite(node->Filename); + LoadSave::hSFile = WriteSavegameChunk("snapshot.bld"); + + try + { + dword_27AA38 = 0; + dword_27AA40 = 0; + LoadSave* rover = LoadSave::head.next; + while (rover != &LoadSave::head) + { + rover->Save(); + if (dword_27AA38 > dword_27AA40) + dword_27AA40 = dword_27AA38; + dword_27AA38 = 0; + rover = rover->next; + } + } + catch (std::runtime_error & err) + { + // Let's not abort for write errors. + Printf(TEXTCOLOR_RED "%s\n", err.what()); + return false; + } + G_WriteSaveHeader(node->SaveTitle); + LoadSave::hSFile = NULL; + + return FinishSavegameWrite(); } class MyLoadSave : public LoadSave @@ -440,47 +438,10 @@ void MyLoadSave::Save(void) void LoadSavedInfo(void) { - FString path = M_GetSavegamesPath() + "game*.sav"; - TArray saves; - D_AddWildFile(saves, path); - int nCount = 0; - for (auto & savename : saves) - { - OpenSaveGameForRead(savename); - auto hFile = ReadSavegameChunk("snapshot.bld"); - if (!hFile.isOpen()) - { - FinishSavegameRead(); - ThrowError("Error loading save file header."); - } - int vc; - short v4; - vc = 0; - v4 = word_27AA54; - if ((uint32_t)hFile.Read(&vc, sizeof(vc)) != sizeof(vc)) - { - continue; - } - if (vc != 0x5653424e/*'VSBN'*/) - { - continue; - } - hFile.Read(&v4, sizeof(v4)); - if (v4 != BYTEVERSION) - { - continue; - } - if ((uint32_t)hFile.Read(&gSaveGameOptions[nCount], sizeof(gSaveGameOptions[0])) != sizeof(gSaveGameOptions[0])) - ThrowError("Error reading save file."); - strcpy(strRestoreGameStrings[gSaveGameOptions[nCount].nSaveGameSlot], gSaveGameOptions[nCount].szUserGameName); - nCount++; - } - FinishSavegameRead(); } void UpdateSavedInfo(int nSlot) { - strcpy(strRestoreGameStrings[gSaveGameOptions[nSlot].nSaveGameSlot], gSaveGameOptions[nSlot].szUserGameName); } static MyLoadSave *myLoadSave; diff --git a/source/blood/src/loadsave.h b/source/blood/src/loadsave.h index 3da580a62..9dac3b0e4 100644 --- a/source/blood/src/loadsave.h +++ b/source/blood/src/loadsave.h @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include "levels.h" +struct FSavegameNode; BEGIN_BLD_NS class LoadSave { @@ -49,12 +50,11 @@ public: virtual void Load(void); void Read(void *, int); void Write(void *, int); - static void LoadGame(char *); - static void SaveGame(char *); + static void LoadGame(FSavegameNode *); + static void SaveGame(FSavegameNode*); }; extern unsigned int gSavedOffset; -extern GAMEOPTIONS gSaveGameOptions[]; extern char *gSaveGamePic[10]; void UpdateSavedInfo(int nSlot); void LoadSavedInfo(void); diff --git a/source/blood/src/map2d.cpp b/source/blood/src/map2d.cpp index 943919d01..e8532289c 100644 --- a/source/blood/src/map2d.cpp +++ b/source/blood/src/map2d.cpp @@ -197,8 +197,8 @@ void CViewMap::sub_25C74(void) videoClearScreen(0); renderDrawMapView(x,y,nZoom>>2,angle); sub_2541C(x,y,nZoom>>2,angle); - char *pTitle = levelGetTitle(); - char *pFilename = levelGetFilename(gGameOptions.nEpisode, gGameOptions.nLevel); + const char *pTitle = levelGetTitle(); + const char *pFilename = levelGetFilename(gGameOptions.nEpisode, gGameOptions.nLevel); if (pTitle) sprintf(pBuffer, "%s: %s", pFilename, pTitle); else @@ -210,10 +210,12 @@ void CViewMap::sub_25C74(void) nViewY = gViewY0S+1; viewDrawText(3, pBuffer, gViewX1S, nViewY, -128, 0, 2, 0, 256); +#if 0 // needs to be generalized if (gViewMap.bFollowMode) viewDrawText(3, "MAP FOLLOW MODE", gViewX1S, nViewY+8, -128, 0, 2, 0, 256); else viewDrawText(3, "MAP SCROLL MODE", gViewX1S, nViewY+8, -128, 0, 2, 0, 256); +#endif if (tm) viewResizeView(viewSize); } diff --git a/source/blood/src/menu.cpp b/source/blood/src/menu.cpp index 2cd2194bf..ef66e2a5d 100644 --- a/source/blood/src/menu.cpp +++ b/source/blood/src/menu.cpp @@ -20,96 +20,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //------------------------------------------------------------------------- -#include "ns.h" // Must come before everything else! -#include "compat.h" -#include "mmulti.h" -#include "common_game.h" -#include "fx_man.h" -#include "music.h" -#include "blood.h" -#include "demo.h" -#include "config.h" -#include "gamemenu.h" -#include "globals.h" -#include "loadsave.h" -#include "menu.h" -#include "messages.h" -#include "network.h" -#include "osdcmds.h" -#include "sfx.h" -#include "screen.h" -#include "sound.h" -#include "view.h" -#include "cmdlib.h" -#include "i_specialpaths.h" +#if 0 -EXTERN_CVAR(Bool, hud_powerupduration) - -BEGIN_BLD_NS - -void SaveGame(CGameMenuItemZEditBitmap *, CGameMenuEvent *); - -void SaveGameProcess(CGameMenuItemChain *); -void SetDifficultyAndStart(CGameMenuItemChain *); -void SetDetail(CGameMenuItemSlider *); -void SetGamma(CGameMenuItemSlider *); -void SetMusicVol(CGameMenuItemSlider *); -void SetSoundVol(CGameMenuItemSlider *); -void SetCDVol(CGameMenuItemSlider *); -void SetDoppler(CGameMenuItemZBool *); -void SetCrosshair(CGameMenuItemZBool *); -void SetCenterHoriz(CGameMenuItemZBool *); -void SetShowPlayerNames(CGameMenuItemZBool *); -void SetShowWeapons(CGameMenuItemZCycle *); -void SetSlopeTilting(CGameMenuItemZBool *); -void SetViewBobbing(CGameMenuItemZBool *); -void SetViewSwaying(CGameMenuItemZBool *); -void SetMouseSensitivity(CGameMenuItemSliderFloat *); -void SetMouseAimFlipped(CGameMenuItemZBool *); -void SetTurnSpeed(CGameMenuItemSlider *); -void ConfigureKeys(CGameMenuItemChain*); -void ResetKeys(CGameMenuItemChain *); -void ResetKeysClassic(CGameMenuItemChain *); -void SetMessages(CGameMenuItemZBool *); -void LoadGame(CGameMenuItemZEditBitmap *, CGameMenuEvent *); -void SetupNetLevels(CGameMenuItemZCycle *); -void StartNetGame(CGameMenuItemChain *); -void SetParentalLock(CGameMenuItemZBool *); -void TenProcess(CGameMenuItem7EA1C *); -void SetupLevelMenuItem(int); -void SetupVideoModeMenu(CGameMenuItemChain *); -void SetVideoMode(CGameMenuItemChain *); -void SetWidescreen(CGameMenuItemZBool *); -void SetFOV(CGameMenuItemSlider *); -void UpdateVideoColorMenu(CGameMenuItemSliderFloat *); -void ResetVideoColor(CGameMenuItemChain *); -void SetWeaponsV10X(CGameMenuItemZBool* pItem); - -#ifdef USE_OPENGL -void SetupVideoPolymostMenu(CGameMenuItemChain *); -#endif - -char strRestoreGameStrings[][16] = -{ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", -}; - -const char *zNetGameTypes[] = -{ - "Cooperative", - "Bloodbath", - "Teams", -}; +// Not yet implemented content kept for reference. Mostly multiplayer related. const char *zMonsterStrings[] = { @@ -140,535 +54,30 @@ const char *zRespawnStrings[] = "Away from Enemies", }; -const char *zDiffStrings[] = -{ - "STILL KICKING", - "PINK ON THE INSIDE", - "LIGHTLY BROILED", - "WELL DONE", - "EXTRA CRISPY", -}; - const char *pzShowWeaponStrings[] = { "OFF", "SPRITE", "VOXEL" }; -char zUserMapName[16]; -const char *zEpisodeNames[6]; -const char *zLevelNames[6][16]; - -static FString MenuGameFuncs[NUMGAMEFUNCTIONS]; -static char const *MenuGameFuncNone = " -None-"; -static char const *pzGamefuncsStrings[NUMGAMEFUNCTIONS + 1]; -static int nGamefuncsValues[NUMGAMEFUNCTIONS + 1]; -static int nGamefuncsNum; - -CGameMenu menuMain; -CGameMenu menuMainWithSave; -CGameMenu menuNetMain; -CGameMenu menuNetStart; -CGameMenu menuEpisode; -CGameMenu menuDifficulty; -CGameMenu menuOptionsOld; -CGameMenu menuControls; -CGameMenu menuMessages; -CGameMenu menuKeys; -CGameMenu menuSaveGame; -CGameMenu menuLoadGame; -CGameMenu menuLoading; -CGameMenu menuSounds; -CGameMenu menuQuit; -CGameMenu menuRestart; -CGameMenu menuCredits; -CGameMenu menuOrder; -CGameMenu menuPlayOnline; -CGameMenu menuParentalLock; -CGameMenu menuSorry; -CGameMenu menuSorry2; -CGameMenu menuNetwork; -CGameMenu menuNetworkHost; -CGameMenu menuNetworkJoin; - -CGameMenuItemQAV itemBloodQAV("", 3, 160, 100, "BDRIP", true); -CGameMenuItemQAV itemCreditsQAV("", 3, 160, 100, "CREDITS", false, true); -CGameMenuItemQAV itemHelp3QAV("", 3, 160, 100, "HELP3", false, false); -CGameMenuItemQAV itemHelp3BQAV("", 3, 160, 100, "HELP3B", false, false); -CGameMenuItemQAV itemHelp4QAV("", 3, 160, 100, "HELP4", false, true); -CGameMenuItemQAV itemHelp5QAV("", 3, 160, 100, "HELP5", false, true); - -CGameMenuItemTitle itemMainTitle("BLOOD", 1, 160, 20, 2038); -CGameMenuItemChain itemMain1("NEW GAME", 1, 0, 45, 320, 1, &menuEpisode, -1, NULL, 0); -//CGameMenuItemChain itemMain2("PLAY ONLINE", 1, 0, 65, 320, 1, &menuPlayOnline, -1, NULL, 0); -CGameMenuItemChain itemMain2("MULTIPLAYER", 1, 0, 65, 320, 1, &menuNetwork, -1, NULL, 0); -CGameMenuItemChain itemMain3("OPTIONS", 1, 0, 85, 320, 1, &menuOptions, -1, NULL, 0); -CGameMenuItemChain itemMain4("LOAD GAME", 1, 0, 105, 320, 1, &menuLoadGame, -1, NULL, 0); -CGameMenuItemChain itemMain5("HELP", 1, 0, 125, 320, 1, &menuOrder, -1, NULL, 0); -CGameMenuItemChain itemMain6("CREDITS", 1, 0, 145, 320, 1, &menuCredits, -1, NULL, 0); -CGameMenuItemChain itemMain7("QUIT", 1, 0, 165, 320, 1, &menuQuit, -1, NULL, 0); - -CGameMenuItemTitle itemMainSaveTitle("BLOOD", 1, 160, 20, 2038); -CGameMenuItemChain itemMainSave1("NEW GAME", 1, 0, 45, 320, 1, &menuEpisode, -1, NULL, 0); -//CGameMenuItemChain itemMainSave2("PLAY ONLINE", 1, 0, 60, 320, 1, &menuPlayOnline, -1, NULL, 0); -CGameMenuItemChain itemMainSave2("OPTIONS", 1, 0, 60, 320, 1, &menuOptions, -1, NULL, 0); -CGameMenuItemChain itemMainSave3("SAVE GAME", 1, 0, 75, 320, 1, &menuSaveGame, -1, SaveGameProcess, 0); -CGameMenuItemChain itemMainSave4("LOAD GAME", 1, 0, 90, 320, 1, &menuLoadGame, -1, NULL, 0); -CGameMenuItemChain itemMainSave5("HELP", 1, 0, 105, 320, 1, &menuOrder, -1, NULL, 0); -CGameMenuItemChain itemMainSave6("CREDITS", 1, 0, 120, 320, 1, &menuCredits, -1, NULL, 0); -CGameMenuItemChain itemMainSave7("END GAME", 1, 0, 135, 320, 1, &menuRestart, -1, NULL, 0); -CGameMenuItemChain itemMainSave8("QUIT", 1, 0, 150, 320, 1, &menuQuit, -1, NULL, 0); - -CGameMenuItemTitle itemEpisodesTitle("EPISODES", 1, 160, 20, 2038); -CGameMenuItemChain7F2F0 itemEpisodes[6]; - -CGameMenuItemTitle itemDifficultyTitle("DIFFICULTY", 1, 160, 20, 2038); -CGameMenuItemChain itemDifficulty1("STILL KICKING", 1, 0, 60, 320, 1, NULL, -1, SetDifficultyAndStart, 0); -CGameMenuItemChain itemDifficulty2("PINK ON THE INSIDE", 1, 0, 80, 320, 1, NULL, -1, SetDifficultyAndStart, 1); -CGameMenuItemChain itemDifficulty3("LIGHTLY BROILED", 1, 0, 100, 320, 1, NULL, -1, SetDifficultyAndStart, 2); -CGameMenuItemChain itemDifficulty4("WELL DONE", 1, 0, 120, 320, 1, NULL, -1, SetDifficultyAndStart, 3); -CGameMenuItemChain itemDifficulty5("EXTRA CRISPY", 1, 0, 140, 320, 1, 0, -1, SetDifficultyAndStart, 4); - -CGameMenuItemTitle itemOptionsOldTitle("OPTIONS", 1, 160, 20, 2038); -CGameMenuItemChain itemOption1("CONTROLS...", 3, 0, 40, 320, 1, &menuControls, -1, NULL, 0); -CGameMenuItemSlider sliderDetail("DETAIL:", 3, 66, 50, 180, gDetail, 0, 4, 1, SetDetail, -1, -1); -CGameMenuItemSlider sliderGamma("GAMMA:", 3, 66, 60, 180, gGamma, 0, 15, 2, SetGamma, -1, -1); -CGameMenuItemSlider sliderMusic("MUSIC:", 3, 66, 70, 180, mus_volume, 0, 256, 48, SetMusicVol, -1, -1); -CGameMenuItemSlider sliderSound("SOUND:", 3, 66, 80, 180, snd_fxvolume, 0, 256, 48, SetSoundVol, -1, -1); -//CGameMenuItemSlider sliderCDAudio("CD AUDIO:", 3, 66, 90, 180, CDVolume, 0, 256, 48, SetCDVol, -1, -1); -CGameMenuItemZBool bool3DAudio("3D AUDIO:", 3, 66, 100, 180, snd_doppler, SetDoppler, NULL, NULL); -CGameMenuItemZBool boolCrosshair("CROSSHAIR:", 3, 66, 110, 180, cl_crosshair, SetCrosshair, NULL, NULL); -CGameMenuItemZCycle itemCycleShowWeapons("SHOW WEAPONS:", 3, 66, 120, 180, 0, SetShowWeapons, pzShowWeaponStrings, ARRAY_SSIZE(pzShowWeaponStrings), 0); -CGameMenuItemZBool boolSlopeTilting("SLOPE TILTING:", 3, 66, 130, 180, cl_slopetilting, SetSlopeTilting, NULL, NULL); -CGameMenuItemZBool boolViewBobbing("VIEW BOBBING:", 3, 66, 140, 180, cl_viewvbob, SetViewBobbing, NULL, NULL); -CGameMenuItemZBool boolViewSwaying("VIEW SWAYING:", 3, 66, 150, 180, cl_viewhbob, SetViewSwaying, NULL, NULL); -CGameMenuItem7EE34 itemOption2("VIDEO MODE...", 3, 0, 160, 320, 1); -CGameMenuItemChain itemChainParentalLock("PARENTAL LOCK", 3, 0, 170, 320, 1, &menuParentalLock, -1, NULL, 0); - -CGameMenuItemTitle itemControlsTitle("CONTROLS", 1, 160, 20, 2038); -CGameMenuItemSliderFloat sliderMouseSpeed("Mouse Sensitivity:", 1, 10, 70, 300, in_mousesensitivity, 0.5f, 16.f, 0.5f, SetMouseSensitivity, -1,-1); -CGameMenuItemZBool boolMouseFlipped("Invert Mouse Aim:", 1, 10, 90, 300, in_mouseflip, SetMouseAimFlipped, NULL, NULL); -CGameMenuItemSlider sliderTurnSpeed("Key Turn Speed:", 1, 10, 110, 300, gTurnSpeed, 64, 128, 4, SetTurnSpeed, -1, -1); -CGameMenuItemChain itemChainKeyList("Configure Keys...", 1, 0, 130, 320, 1, &menuKeys, -1, ConfigureKeys, 0); -CGameMenuItemChain itemChainKeyReset("Reset Keys (default)...", 1, 0, 150, 320, 1, &menuKeys, -1, ResetKeys, 0); -CGameMenuItemChain itemChainKeyResetClassic("Reset Keys (classic)...", 1, 0, 170, 320, 1, &menuKeys, -1, ResetKeysClassic, 0); - CGameMenuItemTitle itemMessagesTitle("MESSAGES", 1, 160, 20, 2038); CGameMenuItemZBool boolMessages("MESSAGES:", 3, 66, 70, 180, 0, SetMessages, NULL, NULL); CGameMenuItemSlider sliderMsgCount("MESSAGE COUNT:", 3, 66, 80, 180, gMessageCount, 1, 16, 1, NULL, -1, -1); CGameMenuItemSlider sliderMsgTime("MESSAGE TIME:", 3, 66, 90, 180, gMessageTime, 1, 8, 1, NULL, -1, -1); -CGameMenuItemZBool boolMsgFont("LARGE FONT:", 3, 66, 100, 180, 0, 0, NULL, NULL); -CGameMenuItemZBool boolMsgIncoming("INCOMING:", 3, 66, 110, 180, 0, 0, NULL, NULL); -CGameMenuItemZBool boolMsgSelf("SELF PICKUP:", 3, 66, 120, 180, 0, 0, NULL, NULL); -CGameMenuItemZBool boolMsgOther("OTHER PICKUP:", 3, 66, 130, 180, 0, 0, NULL, NULL); -CGameMenuItemZBool boolMsgRespawn("RESPAWN:", 3, 66, 140, 180, 0, 0, NULL, NULL); -CGameMenuItemTitle itemKeysTitle("KEY SETUP", 1, 160, 20, 2038); -CGameMenuItemKeyList itemKeyList("", 3, 56, 40, 200, 16, NUMGAMEFUNCTIONS, 0); - -CGameMenuItemTitle itemSaveTitle("Save Game", 1, 160, 20, 2038); -CGameMenuItemZEditBitmap itemSaveGame1(NULL, 3, 20, 60, 320, strRestoreGameStrings[0], 16, 1, SaveGame, 0); -CGameMenuItemZEditBitmap itemSaveGame2(NULL, 3, 20, 70, 320, strRestoreGameStrings[1], 16, 1, SaveGame, 1); -CGameMenuItemZEditBitmap itemSaveGame3(NULL, 3, 20, 80, 320, strRestoreGameStrings[2], 16, 1, SaveGame, 2); -CGameMenuItemZEditBitmap itemSaveGame4(NULL, 3, 20, 90, 320, strRestoreGameStrings[3], 16, 1, SaveGame, 3); -CGameMenuItemZEditBitmap itemSaveGame5(NULL, 3, 20, 100, 320, strRestoreGameStrings[4], 16, 1, SaveGame, 4); -CGameMenuItemZEditBitmap itemSaveGame6(NULL, 3, 20, 110, 320, strRestoreGameStrings[5], 16, 1, SaveGame, 5); -CGameMenuItemZEditBitmap itemSaveGame7(NULL, 3, 20, 120, 320, strRestoreGameStrings[6], 16, 1, SaveGame, 6); -CGameMenuItemZEditBitmap itemSaveGame8(NULL, 3, 20, 130, 320, strRestoreGameStrings[7], 16, 1, SaveGame, 7); -CGameMenuItemZEditBitmap itemSaveGame9(NULL, 3, 20, 140, 320, strRestoreGameStrings[8], 16, 1, SaveGame, 8); -CGameMenuItemZEditBitmap itemSaveGame10(NULL, 3, 20, 150, 320, strRestoreGameStrings[9], 16, 1, SaveGame, 9); -CGameMenuItemBitmapLS itemSaveGamePic(NULL, 3, 0, 0, 2050); - -CGameMenuItemTitle itemLoadTitle("Load Game", 1, 160, 20, 2038); -CGameMenuItemZEditBitmap itemLoadGame1(NULL, 3, 20, 60, 320, strRestoreGameStrings[0], 16, 1, LoadGame, 0); -CGameMenuItemZEditBitmap itemLoadGame2(NULL, 3, 20, 70, 320, strRestoreGameStrings[1], 16, 1, LoadGame, 1); -CGameMenuItemZEditBitmap itemLoadGame3(NULL, 3, 20, 80, 320, strRestoreGameStrings[2], 16, 1, LoadGame, 2); -CGameMenuItemZEditBitmap itemLoadGame4(NULL, 3, 20, 90, 320, strRestoreGameStrings[3], 16, 1, LoadGame, 3); -CGameMenuItemZEditBitmap itemLoadGame5(NULL, 3, 20, 100, 320, strRestoreGameStrings[4], 16, 1, LoadGame, 4); -CGameMenuItemZEditBitmap itemLoadGame6(NULL, 3, 20, 110, 320, strRestoreGameStrings[5], 16, 1, LoadGame, 5); -CGameMenuItemZEditBitmap itemLoadGame7(NULL, 3, 20, 120, 320, strRestoreGameStrings[6], 16, 1, LoadGame, 6); -CGameMenuItemZEditBitmap itemLoadGame8(NULL, 3, 20, 130, 320, strRestoreGameStrings[7], 16, 1, LoadGame, 7); -CGameMenuItemZEditBitmap itemLoadGame9(NULL, 3, 20, 140, 320, strRestoreGameStrings[8], 16, 1, LoadGame, 8); -CGameMenuItemZEditBitmap itemLoadGame10(NULL, 3, 20, 150, 320, strRestoreGameStrings[9], 16, 1, LoadGame, 9); -CGameMenuItemBitmapLS itemLoadGamePic(NULL, 3, 0, 0, 2518); - -CGameMenuItemTitle itemNetStartTitle("MULTIPLAYER", 1, 160, 20, 2038); -CGameMenuItemZCycle itemNetStart1("GAME:", 3, 66, 60, 180, 0, 0, zNetGameTypes, 3, 0); -CGameMenuItemZCycle itemNetStart2("EPISODE:", 3, 66, 70, 180, 0, SetupNetLevels, NULL, 0, 0); -CGameMenuItemZCycle itemNetStart3("LEVEL:", 3, 66, 80, 180, 0, NULL, NULL, 0, 0); -CGameMenuItemZCycle itemNetStart4("DIFFICULTY:", 3, 66, 90, 180, 0, 0, zDiffStrings, 5, 0); -CGameMenuItemZCycle itemNetStart5("MONSTERS:", 3, 66, 100, 180, 0, 0, zMonsterStrings, 3, 0); -CGameMenuItemZCycle itemNetStart6("WEAPONS:", 3, 66, 110, 180, 0, 0, zWeaponStrings, 4, 0); -CGameMenuItemZCycle itemNetStart7("ITEMS:", 3, 66, 120, 180, 0, 0, zItemStrings, 3, 0); -CGameMenuItemZBool itemNetStart8("FRIENDLY FIRE:", 3, 66, 130, 180, true, 0, NULL, NULL); -CGameMenuItemZBool itemNetStart9("KEEP KEYS ON RESPAWN:", 3, 66, 140, 180, false, 0, NULL, NULL); -CGameMenuItemZBool itemNetStart10("V1.0x WEAPONS BALANCE:", 3, 66, 150, 180, false, 0, NULL, NULL); -CGameMenuItemZEdit itemNetStart11("USER MAP:", 3, 66, 160, 180, zUserMapName, 13, 0, NULL, 0); -CGameMenuItemChain itemNetStart12("START GAME", 1, 66, 175, 280, 0, 0, -1, StartNetGame, 0); - -CGameMenuItemText itemLoadingText("LOADING...", 1, 160, 100, 1); - -CGameMenuItemTitle itemSoundsTitle("SOUNDS", 1, 160, 20, 2038); -CGameMenuItemSlider itemSoundsMusic("MUSIC:", 3, 40, 60, 180, mus_volume, 0, 256, 48, SetMusicVol, -1, -1); -CGameMenuItemSlider itemSoundsSound("SOUND:", 3, 40, 70, 180, snd_fxvolume, 0, 256, 48, SetSoundVol, -1, -1); -//CGameMenuItemSlider itemSoundsCDAudio("CD AUDIO:", 3, 40, 80, 180, CDVolume, 0, 256, 48, SetCDVol, -1, -1); -CGameMenuItemZBool itemSounds3DAudio("3D SOUND:", 3, 40, 90, 180, snd_doppler, SetDoppler, NULL, NULL); - -CGameMenuItemTitle itemQuitTitle("QUIT", 1, 160, 20, 2038); -CGameMenuItemText itemQuitText1("Do you really want to quit?", 0, 160, 100, 1); -CGameMenuItemYesNoQuit itemQuitYesNo("[Y/N]", 0, 20, 110, 280, 1, 0); - -CGameMenuItemTitle itemRestartTitle("RESTART GAME", 1, 160, 20, 2038); -CGameMenuItemText itemRestartText1("Do you really want to restart game?", 0, 160, 100, 1); -CGameMenuItemYesNoQuit itemRestartYesNo("[Y/N]", 0, 20, 110, 280, 1, 1); - -CGameMenuItemPicCycle itemCreditsPicCycle(0, 0, NULL, NULL, 0, 0); -CGameMenuItemPicCycle itemOrderPicCycle(0, 0, NULL, NULL, 0, 0); - -CGameMenuItemTitle itemParentalLockTitle("PARENTAL LOCK", 1, 160, 20, 2038); -CGameMenuItemZBool itemParentalLockToggle("LOCK:", 3, 66, 70, 180, 0, SetParentalLock, NULL, NULL); -CGameMenuItemPassword itemParentalLockPassword("SET PASSWORD:", 3, 160, 80); - -CGameMenuItemPicCycle itemSorryPicCycle(0, 0, NULL, NULL, 0, 0); -CGameMenuItemText itemSorryText1("Loading and saving games", 0, 160, 90, 1); -CGameMenuItemText itemSorryText2("not supported", 0, 160, 100, 1); -CGameMenuItemText itemSorryText3("in this demo version of Blood.", 0, 160, 110, 1); - -CGameMenuItemText itemSorry2Text1("Buy the complete version of", 0, 160, 90, 1); -CGameMenuItemText itemSorry2Text2("Blood for three new episodes", 0, 160, 100, 1); -CGameMenuItemText itemSorry2Text3("plus eight BloodBath-only levels!", 0, 160, 110, 1); - -CGameMenuItemTitle unk_26E06C(" ONLINE ", 1, 160, 20, 2038); -CGameMenuItem7EA1C unk_26E090("DWANGO", 1, 0, 45, 320, "matt", "DWANGO", 1, -1, NULL, 0); -CGameMenuItem7EA1C unk_26E0E8("RTIME", 1, 0, 65, 320, "matt", "RTIME", 1, -1, NULL, 0); -CGameMenuItem7EA1C unk_26E140("HEAT", 1, 0, 85, 320, "matt", "HEAT", 1, -1, NULL, 0); -CGameMenuItem7EA1C unk_26E198("KALI", 1, 0, 105, 320, "matt", "KALI", 1, -1, NULL, 0); -CGameMenuItem7EA1C unk_26E1F0("MPATH", 1, 0, 125, 320, "matt", "MPATH", 1, -1, NULL, 0); -CGameMenuItem7EA1C unk_26E248("TEN", 1, 0, 145, 320, "matt", "TEN", 1, -1, TenProcess, 0); - - -// static int32_t newresolution, newrendermode, newfullscreen, newvsync; - -enum resflags_t { - RES_FS = 0x1, - RES_WIN = 0x2, -}; - -#define MAXRESOLUTIONSTRINGLENGTH 19 - -struct resolution_t { - int32_t xdim, ydim; - int32_t flags; - int32_t bppmax; - char name[MAXRESOLUTIONSTRINGLENGTH]; -}; - -resolution_t gResolution[MAXVALIDMODES]; -int gResolutionNum; -const char *gResolutionName[MAXVALIDMODES]; - -CGameMenu menuOptions; -CGameMenu menuOptionsGame; -CGameMenu menuOptionsDisplay; -CGameMenu menuOptionsDisplayColor; -CGameMenu menuOptionsDisplayMode; -#ifdef USE_OPENGL -CGameMenu menuOptionsDisplayPolymost; -#endif -CGameMenu menuOptionsSound; -CGameMenu menuOptionsPlayer; -CGameMenu menuOptionsControl; - -void SetupOptionsSound(CGameMenuItemChain *pItem); - -CGameMenuItemTitle itemOptionsTitle("OPTIONS", 1, 160, 20, 2038); -CGameMenuItemChain itemOptionsChainGame("GAME SETUP", 1, 0, 50, 320, 1, &menuOptionsGame, -1, NULL, 0); -CGameMenuItemChain itemOptionsChainDisplay("DISPLAY SETUP", 1, 0, 70, 320, 1, &menuOptionsDisplay, -1, NULL, 0); -CGameMenuItemChain itemOptionsChainSound("SOUND SETUP", 1, 0, 90, 320, 1, &menuOptionsSound, -1, SetupOptionsSound, 0); -CGameMenuItemChain itemOptionsChainPlayer("PLAYER SETUP", 1, 0, 110, 320, 1, &menuOptionsPlayer, -1, NULL, 0); -CGameMenuItemChain itemOptionsChainControl("CONTROL SETUP", 1, 0, 130, 320, 1, &menuOptionsControl, -1, NULL, 0); -CGameMenuItemChain itemOptionsChainOld("OLD MENU", 1, 0, 170, 320, 1, &menuOptionsOld, -1, NULL, 0); - -const char *pzAutoAimStrings[] = { - "NEVER", - "ALWAYS", - "HITSCAN ONLY" -}; - -const char *pzWeaponSwitchStrings[] = { - "NEVER", - "IF NEW", - "BY RATING" -}; - -void SetAutoAim(CGameMenuItemZCycle *); -void SetLevelStats(CGameMenuItemZBool *); -void SetPowerupDuration(CGameMenuItemZBool *); -void SetShowMapTitle(CGameMenuItemZBool*); -void SetWeaponSwitch(CGameMenuItemZCycle *pItem); CGameMenuItemTitle itemOptionsGameTitle("GAME SETUP", 1, 160, 20, 2038); -/////////////// -CGameMenuItemZBool itemOptionsGameBoolWeaponsV10X("V1.0x WEAPONS BALANCE:", 3, 66, 130, 180, gWeaponsV10x, SetWeaponsV10X, NULL, NULL); -/////////////////// -CGameMenuItemZBool itemOptionsGameBoolShowPlayerNames("SHOW PLAYER NAMES:", 3, 66, 60, 180, cl_idplayers, SetShowPlayerNames, NULL, NULL); CGameMenuItemZCycle itemOptionsGameShowWeapons("SHOW WEAPONS:", 3, 66, 70, 180, 0, SetShowWeapons, pzShowWeaponStrings, ARRAY_SSIZE(pzShowWeaponStrings), 0); CGameMenuItemZBool itemOptionsGameBoolSlopeTilting("SLOPE TILTING:", 3, 66, 80, 180, cl_slopetilting, SetSlopeTilting, NULL, NULL); CGameMenuItemZBool itemOptionsGameBoolViewBobbing("VIEW BOBBING:", 3, 66, 90, 180, cl_viewvbob, SetViewBobbing, NULL, NULL); CGameMenuItemZBool itemOptionsGameBoolViewSwaying("VIEW SWAYING:", 3, 66, 100, 180, cl_viewhbob, SetViewSwaying, NULL, NULL); -CGameMenuItemZCycle itemOptionsGameBoolAutoAim("AUTO AIM:", 3, 66, 110, 180, 0, SetAutoAim, pzAutoAimStrings, ARRAY_SSIZE(pzAutoAimStrings), 0); -CGameMenuItemZCycle itemOptionsGameWeaponSwitch("EQUIP PICKUPS:", 3, 66, 120, 180, 0, SetWeaponSwitch, pzWeaponSwitchStrings, ARRAY_SSIZE(pzWeaponSwitchStrings), 0); -CGameMenuItemChain itemOptionsGameChainParentalLock("PARENTAL LOCK", 3, 0, 120, 320, 1, &menuParentalLock, -1, NULL, 0); -CGameMenuItemTitle itemOptionsDisplayTitle("DISPLAY SETUP", 1, 160, 20, 2038); -CGameMenuItemChain itemOptionsDisplayColor("COLOR CORRECTION", 3, 66, 60, 180, 0, &menuOptionsDisplayColor, -1, NULL, 0); -CGameMenuItemChain itemOptionsDisplayMode("VIDEO MODE", 3, 66, 70, 180, 0, &menuOptionsDisplayMode, -1, SetupVideoModeMenu, 0); -CGameMenuItemZBool itemOptionsDisplayBoolCrosshair("CROSSHAIR:", 3, 66, 80, 180, cl_crosshair, SetCrosshair, NULL, NULL); CGameMenuItemZBool itemOptionsDisplayBoolCenterHoriz("CENTER HORIZON LINE:", 3, 66, 90, 180, r_horizcenter, SetCenterHoriz, NULL, NULL); -CGameMenuItemZBool itemOptionsDisplayBoolLevelStats("LEVEL STATS:", 3, 66, 100, 180, hud_stats, SetLevelStats, NULL, NULL); CGameMenuItemZBool itemOptionsDisplayBoolPowerupDuration("POWERUP DURATION:", 3, 66, 110, 180, hud_powerupduration, SetPowerupDuration, NULL, NULL); CGameMenuItemZBool itemOptionsDisplayBoolShowMapTitle("MAP TITLE:", 3, 66, 120, 180, hud_showmapname, SetShowMapTitle, NULL, NULL); -CGameMenuItemZBool itemOptionsDisplayBoolMessages("MESSAGES:", 3, 66, 130, 180, hud_messages, SetMessages, NULL, NULL); -CGameMenuItemZBool itemOptionsDisplayBoolWidescreen("WIDESCREEN:", 3, 66, 140, 180, r_usenewaspect, SetWidescreen, NULL, NULL); -CGameMenuItemSlider itemOptionsDisplayFOV("FOV:", 3, 66, 150, 180, &r_fov.Value, 75, 140, 5, SetFOV, -1, -1, kMenuSliderValue); -#ifdef USE_OPENGL -CGameMenuItemChain itemOptionsDisplayPolymost("POLYMOST SETUP", 3, 66, 160, 180, 0, &menuOptionsDisplayPolymost, -1, SetupVideoPolymostMenu, 0); -#endif -const char *pzRendererStrings[] = { - "CLASSIC", - "POLYMOST" -}; - -const int nRendererValues[] = { - REND_CLASSIC, - REND_POLYMOST -}; - -const char *pzVSyncStrings[] = { - "ADAPTIVE", - "OFF", - "ON" -}; - -const int nVSyncValues[] = { - -1, - 0, - 1 -}; - -const char *pzFrameLimitStrings[] = { - "30 FPS", - "60 FPS", - "75 FPS", - "100 FPS", - "120 FPS", - "144 FPS", - "165 FPS", - "240 FPS" -}; - -const int nFrameLimitValues[] = { - 30, - 60, - 75, - 100, - 120, - 144, - 165, - 240 -}; - - -void PreDrawVideoModeMenu(CGameMenuItem *); - -CGameMenuItemTitle itemOptionsDisplayModeTitle("VIDEO MODE", 1, 160, 20, 2038); -CGameMenuItemZCycle itemOptionsDisplayModeResolution("RESOLUTION:", 3, 66, 60, 180, 0, NULL, NULL, 0, 0, true); -CGameMenuItemZCycle itemOptionsDisplayModeRenderer("RENDERER:", 3, 66, 70, 180, 0, NULL, pzRendererStrings, 2, 0); -CGameMenuItemZBool itemOptionsDisplayModeFullscreen("FULLSCREEN:", 3, 66, 80, 180, 0, NULL, NULL, NULL); -CGameMenuItemZCycle itemOptionsDisplayModeVSync("VSYNC:", 3, 66, 90, 180, 0, NULL, pzVSyncStrings, 3, 0); -CGameMenuItemChain itemOptionsDisplayModeApply("APPLY CHANGES", 3, 66, 125, 180, 0, NULL, 0, SetVideoMode, 0); - -void PreDrawDisplayColor(CGameMenuItem *); - -CGameMenuItemTitle itemOptionsDisplayColorTitle("COLOR CORRECTION", 1, 160, 20, -1); -CGameMenuItemSliderFloat itemOptionsDisplayColorGamma("GAMMA:", 3, 66, 140, 180, &vid_gamma.Value, 0.3f, 4.f, 0.1f, UpdateVideoColorMenu, -1, -1, kMenuSliderValue); -CGameMenuItemSliderFloat itemOptionsDisplayColorContrast("CONTRAST:", 3, 66, 150, 180, &vid_contrast.Value, 0.1f, 2.7f, 0.05f, UpdateVideoColorMenu, -1, -1, kMenuSliderValue); -CGameMenuItemSliderFloat itemOptionsDisplayColorBrightness("BRIGHTNESS:", 3, 66, 160, 180, &vid_brightness.Value, -0.8f, 0.8f, 0.05f, UpdateVideoColorMenu, -1, -1, kMenuSliderValue); -CGameMenuItemSliderFloat itemOptionsDisplayColorVisibility("VISIBILITY:", 3, 66, 170, 180, &r_ambientlight.Value, 0.125f, 4.f, 0.125f, UpdateVideoColorMenu, -1, -1, kMenuSliderValue); -CGameMenuItemChain itemOptionsDisplayColorReset("RESET TO DEFAULTS", 3, 66, 180, 180, 0, NULL, 0, ResetVideoColor, 0); - -const char *pzTextureModeStrings[] = { - "CLASSIC", - "FILTERED" -}; - -#ifdef USE_OPENGL -int nTextureModeValues[] = { - TEXFILTER_OFF, - TEXFILTER_ON -}; -#endif - -const char *pzAnisotropyStrings[] = { - "MAX", - "NONE", - "2X", - "4X", - "8X", - "16X" -}; - -int nAnisotropyValues[] = { - 0, - 1, - 2, - 4, - 8, - 16 -}; - -const char *pzTexQualityStrings[] = { - "FULL", - "HALF", - "BARF" -}; - - -void UpdateTextureMode(CGameMenuItemZCycle *pItem); -void UpdateAnisotropy(CGameMenuItemZCycle *pItem); -void UpdateTrueColorTextures(CGameMenuItemZBool *pItem); -void UpdateTexQuality(CGameMenuItemZCycle *pItem); -void UpdatePreloadCache(CGameMenuItemZBool *pItem); -void UpdateDetailTex(CGameMenuItemZBool *pItem); -void UpdateGlowTex(CGameMenuItemZBool *pItem); -void Update3DModels(CGameMenuItemZBool *pItem); -void UpdateDeliriumBlur(CGameMenuItemZBool *pItem); -#ifdef USE_OPENGL -void PreDrawDisplayPolymost(CGameMenuItem *pItem); -CGameMenuItemTitle itemOptionsDisplayPolymostTitle("POLYMOST SETUP", 1, 160, 20, 2038); -CGameMenuItemZCycle itemOptionsDisplayPolymostTextureMode("TEXTURE MODE:", 3, 66, 60, 180, 0, UpdateTextureMode, pzTextureModeStrings, 2, 0); -CGameMenuItemZCycle itemOptionsDisplayPolymostAnisotropy("ANISOTROPY:", 3, 66, 70, 180, 0, UpdateAnisotropy, pzAnisotropyStrings, 6, 0); -CGameMenuItemZBool itemOptionsDisplayPolymostTrueColorTextures("TRUE COLOR TEXTURES:", 3, 66, 80, 180, 0, UpdateTrueColorTextures, NULL, NULL); -CGameMenuItemZBool itemOptionsDisplayPolymostPreloadCache("PRE-LOAD MAP TEXTURES:", 3, 66, 100, 180, 0, UpdatePreloadCache, NULL, NULL); -CGameMenuItemZBool itemOptionsDisplayPolymostDetailTex("DETAIL TEXTURES:", 3, 66, 120, 180, 0, UpdateDetailTex, NULL, NULL); -CGameMenuItemZBool itemOptionsDisplayPolymostGlowTex("GLOW TEXTURES:", 3, 66, 130, 180, 0, UpdateGlowTex, NULL, NULL); -CGameMenuItemZBool itemOptionsDisplayPolymost3DModels("3D MODELS:", 3, 66, 140, 180, 0, Update3DModels, NULL, NULL); -CGameMenuItemZBool itemOptionsDisplayPolymostDeliriumBlur("DELIRIUM EFFECT BLUR:", 3, 66, 150, 180, 0, UpdateDeliriumBlur, NULL, NULL); -#endif - -void UpdateSoundToggle(CGameMenuItemZBool *pItem); -void UpdateMusicToggle(CGameMenuItemZBool *pItem); -void Update3DToggle(CGameMenuItemZBool *pItem); -void UpdateCDToggle(CGameMenuItemZBool *pItem); -void UpdateSoundVolume(CGameMenuItemSlider *pItem); -void UpdateMusicVolume(CGameMenuItemSlider *pItem); -void UpdateSoundRate(CGameMenuItemZCycle *pItem); -void UpdateNumVoices(CGameMenuItemSlider *pItem); -void UpdateMusicDevice(CGameMenuItemZCycle *pItem); -void SetSound(CGameMenuItemChain *pItem); -void PreDrawSound(CGameMenuItem *pItem); -const char *pzSoundRateStrings[] = { - "22050HZ", - "44100HZ", - "48000HZ" -}; - -int nSoundRateValues[] = { - 22050, - 44100, - 48000 -}; - -int nMusicDeviceValues[] = { - ASS_OPL3, -#ifdef _WIN32 - ASS_WinMM, -#endif -}; - -const char *pzMusicDeviceStrings[] = { - "OPL3(SB/ADLIB)", -#ifdef _WIN32 - "SYSTEM MIDI", -#endif -}; - -CGameMenuItemTitle itemOptionsSoundTitle("SOUND SETUP", 1, 160, 20, 2038); -CGameMenuItemZBool itemOptionsSoundSoundToggle("SOUND:", 3, 66, 60, 180, false, UpdateSoundToggle, NULL, NULL); -CGameMenuItemZBool itemOptionsSoundMusicToggle("MUSIC:", 3, 66, 70, 180, false, UpdateMusicToggle, NULL, NULL); -CGameMenuItemZBool itemOptionsSound3DToggle("3D AUDIO:", 3, 66, 80, 180, false, Update3DToggle, NULL, NULL); -CGameMenuItemSlider itemOptionsSoundSoundVolume("SOUND VOLUME:", 3, 66, 90, 180, &snd_fxvolume.Value, 0, 256, 48, UpdateSoundVolume, -1, -1, kMenuSliderPercent); -CGameMenuItemSlider itemOptionsSoundMusicVolume("MUSIC VOLUME:", 3, 66, 100, 180, &mus_volume.Value, 0, 256, 48, UpdateMusicVolume, -1, -1, kMenuSliderPercent); -CGameMenuItemZCycle itemOptionsSoundSampleRate("SAMPLE RATE:", 3, 66, 110, 180, 0, UpdateSoundRate, pzSoundRateStrings, 3, 0); -CGameMenuItemSlider itemOptionsSoundNumVoices("VOICES:", 3, 66, 120, 180, snd_numvoices, 16, 256, 16, UpdateNumVoices, -1, -1, kMenuSliderValue); -CGameMenuItemZBool itemOptionsSoundCDToggle("REDBOOK AUDIO:", 3, 66, 130, 180, false, UpdateCDToggle, NULL, NULL); -CGameMenuItemZCycle itemOptionsSoundMusicDevice("MUSIC DEVICE:", 3, 66, 140, 180, 0, UpdateMusicDevice, pzMusicDeviceStrings, ARRAY_SIZE(pzMusicDeviceStrings), 0); -CGameMenuItemChain itemOptionsSoundApplyChanges("APPLY CHANGES", 3, 66, 150, 180, 0, NULL, 0, SetSound, 0); - - -void UpdatePlayerName(CGameMenuItemZEdit *pItem, CGameMenuEvent *pEvent); - -CGameMenuItemTitle itemOptionsPlayerTitle("PLAYER SETUP", 1, 160, 20, 2038); -// This won't work without messing around with stuff. So it'll have to wait for the new options menu. -//CGameMenuItemZEdit itemOptionsPlayerName("PLAYER NAME:", 3, 66, 60, 180, *playername, MAXPLAYERNAME, 0, UpdatePlayerName, 0); - -CGameMenu menuOptionsControlKeyboard; -CGameMenu menuOptionsControlMouse; -CGameMenu menuOptionsControlMouseButtonAssignment; - -void SetupMouseMenu(CGameMenuItemChain *pItem); - -CGameMenuItemTitle itemOptionsControlTitle("CONTROL SETUP", 1, 160, 20, 2038); -CGameMenuItemChain itemOptionsControlKeyboard("CONFIGURE CONTROLS", 1, 0, 60, 320, 1, &menuOptionsControlKeyboard, -1, NULL, 0); -CGameMenuItemChain itemOptionsControlMouse("MOUSE SETUP", 1, 0, 80, 320, 1, &menuOptionsControlMouse, -1, SetupMouseMenu, 0); - -CGameMenuItemTitle itemOptionsControlKeyboardTitle("CONFIGURE CONTROLS", 1, 160, 20, 2038); -CGameMenuItemChain itemOptionsControlKeyboardList("Edit Configuration...", 1, 0, 60, 320, 1, &menuKeys, -1, ConfigureKeys, 0); -CGameMenuItemChain itemOptionsControlKeyboardReset("Reset Configuration (default)...", 1, 0, 80, 320, 1, &menuKeys, -1, ResetKeys, 0); -CGameMenuItemChain itemOptionsControlKeyboardResetClassic("Reset Configuration (classic)...", 1, 0, 100, 320, 1, &menuKeys, -1, ResetKeysClassic, 0); - -void SetMouseFilterInput(CGameMenuItemZBool *pItem); -void SetMouseAimMode(CGameMenuItemZBool *pItem); -void SetMouseVerticalAim(CGameMenuItemZBool *pItem); -void SetMouseXScale(CGameMenuItemSlider *pItem); -void SetMouseYScale(CGameMenuItemSlider *pItem); -void SetMouseDigitalAxis(CGameMenuItemZCycle *pItem); - -void PreDrawControlMouse(CGameMenuItem *pItem); - -void SetupMouseButtonMenu(CGameMenuItemChain *pItem); - -CGameMenuItemTitle itemOptionsControlMouseTitle("MOUSE SETUP", 1, 160, 20, 2038); -//CGameMenuItemChain itemOptionsControlMouseButton("BUTTON ASSIGNMENT", 3, 66, 60, 180, 0, &menuOptionsControlMouseButtonAssignment, 0, SetupMouseButtonMenu, 0); -CGameMenuItemSliderFloat itemOptionsControlMouseSensitivity("SENSITIVITY:", 3, 66, 70, 180, &in_mousesensitivity.Value, 0.5f, 16.f, 0.5f, SetMouseSensitivity, -1, -1, kMenuSliderValue); -CGameMenuItemZBool itemOptionsControlMouseAimFlipped("INVERT AIMING:", 3, 66, 80, 180, false, SetMouseAimFlipped, NULL, NULL); -CGameMenuItemZBool itemOptionsControlMouseFilterInput("FILTER INPUT:", 3, 66, 90, 180, false, SetMouseFilterInput, NULL, NULL); -CGameMenuItemZBool itemOptionsControlMouseAimMode("AIMING TYPE:", 3, 66, 100, 180, false, SetMouseAimMode, "HOLD", "TOGGLE"); -CGameMenuItemZBool itemOptionsControlMouseVerticalAim("VERTICAL AIMING:", 3, 66, 110, 180, false, SetMouseVerticalAim, NULL, NULL); -CGameMenuItemSlider itemOptionsControlMouseXScale("X-SCALE:", 3, 66, 120, 180, (int*)&in_mousescalex, 0, 65536, 1024, SetMouseXScale, -1, -1, kMenuSliderQ16); -CGameMenuItemSlider itemOptionsControlMouseYScale("Y-SCALE:", 3, 66, 130, 180, (int*)&in_mousescaley, 0, 65536, 1024, SetMouseYScale, -1, -1, kMenuSliderQ16); -/* -CGameMenuItemZCycle itemOptionsControlMouseDigitalUp("DIGITAL UP", 3, 66, 140, 180, 0, SetMouseDigitalAxis, NULL, 0, 0, true); -CGameMenuItemZCycle itemOptionsControlMouseDigitalDown("DIGITAL DOWN", 3, 66, 150, 180, 0, SetMouseDigitalAxis, NULL, 0, 0, true); -CGameMenuItemZCycle itemOptionsControlMouseDigitalLeft("DIGITAL LEFT", 3, 66, 160, 180, 0, SetMouseDigitalAxis, NULL, 0, 0, true); -CGameMenuItemZCycle itemOptionsControlMouseDigitalRight("DIGITAL RIGHT", 3, 66, 170, 180, 0, SetMouseDigitalAxis, NULL, 0, 0, true); -*/ - -void SetupNetworkMenu(void); -void SetupNetworkHostMenu(CGameMenuItemChain *pItem); -void SetupNetworkJoinMenu(CGameMenuItemChain *pItem); -void NetworkHostGame(CGameMenuItemChain *pItem); -void NetworkJoinGame(CGameMenuItemChain *pItem); - -char zNetAddressBuffer[16] = "localhost"; -char zNetPortBuffer[6]; - -CGameMenuItemTitle itemNetworkTitle("MULTIPLAYER", 1, 160, 20, 2038); -CGameMenuItemChain itemNetworkHost("HOST A GAME", 1, 0, 80, 320, 1, &menuNetworkHost, -1, SetupNetworkHostMenu, 0); -CGameMenuItemChain itemNetworkJoin("JOIN A GAME", 1, 0, 100, 320, 1, &menuNetworkJoin, -1, SetupNetworkJoinMenu, 0); CGameMenuItemTitle itemNetworkHostTitle("HOST A GAME", 1, 160, 20, 2038); CGameMenuItemSlider itemNetworkHostPlayerNum("PLAYER NUMBER:", 3, 66, 70, 180, 1, 2, kMaxPlayers, 1, NULL, -1, -1, kMenuSliderValue); @@ -680,732 +89,6 @@ CGameMenuItemZEdit itemNetworkJoinAddress("NETWORK ADDRESS:", 3, 66, 70, 180, zN CGameMenuItemZEdit itemNetworkJoinPort("NETWORK PORT:", 3, 66, 80, 180, zNetPortBuffer, 6, 0, NULL, 0); CGameMenuItemChain itemNetworkJoinJoin("JOIN A GAME", 3, 66, 100, 180, 1, NULL, -1, NetworkJoinGame, 0); -// There is no better way to do this than manually. - -#define MENUMOUSEFUNCTIONS 12 - -static char const *MenuMouseNames[MENUMOUSEFUNCTIONS] = { - "Button 1", - "Double Button 1", - "Button 2", - "Double Button 2", - "Button 3", - "Double Button 3", - - "Wheel Up", - "Wheel Down", - - "Button 4", - "Double Button 4", - "Button 5", - "Double Button 5", -}; - -static int32_t MenuMouseDataIndex[MENUMOUSEFUNCTIONS][2] = { - { 0, 0, }, - { 0, 1, }, - { 1, 0, }, - { 1, 1, }, - { 2, 0, }, - { 2, 1, }, - - // note the mouse wheel - { 4, 0, }, - { 5, 0, }, - - { 3, 0, }, - { 3, 1, }, - { 6, 0, }, - { 6, 1, }, -}; - -void SetMouseButton(CGameMenuItemZCycle *pItem); - -CGameMenuItemZCycle *pItemOptionsControlMouseButton[MENUMOUSEFUNCTIONS]; - -void SetupLoadingScreen(void) -{ - menuLoading.Add(&itemLoadingText, true); -} - -void SetupKeyListMenu(void) -{ - menuKeys.Add(&itemKeysTitle, false); - menuKeys.Add(&itemKeyList, true); - menuKeys.Add(&itemBloodQAV, false); -} - -void SetupMessagesMenu(void) -{ - menuMessages.Add(&itemMessagesTitle, false); - menuMessages.Add(&boolMessages, true); - menuMessages.Add(&sliderMsgCount, false); - menuMessages.Add(&sliderMsgTime, false); - menuMessages.Add(&boolMsgFont, false); - menuMessages.Add(&boolMsgIncoming, false); - menuMessages.Add(&boolMsgSelf, false); - menuMessages.Add(&boolMsgOther, false); - menuMessages.Add(&boolMsgRespawn, false); - menuMessages.Add(&itemBloodQAV, false); -} - -void SetupControlsMenu(void) -{ - sliderMouseSpeed.fValue = ClipRangeF(in_mousesensitivity, sliderMouseSpeed.fRangeLow, sliderMouseSpeed.fRangeHigh); - sliderTurnSpeed.nValue = ClipRange(gTurnSpeed, sliderTurnSpeed.nRangeLow, sliderTurnSpeed.nRangeHigh); - boolMouseFlipped.at20 = in_mouseflip; - menuControls.Add(&itemControlsTitle, false); - menuControls.Add(&sliderMouseSpeed, true); - menuControls.Add(&boolMouseFlipped, false); - menuControls.Add(&sliderTurnSpeed, false); - menuControls.Add(&itemChainKeyList, false); - menuControls.Add(&itemChainKeyReset, false); - menuControls.Add(&itemChainKeyResetClassic, false); - menuControls.Add(&itemBloodQAV, false); -} - -void SetupOptionsOldMenu(void) -{ - sliderDetail.nValue = ClipRange(gDetail, sliderDetail.nRangeLow, sliderDetail.nRangeHigh); - sliderGamma.nValue = ClipRange(gGamma, sliderGamma.nRangeLow, sliderGamma.nRangeHigh); - sliderMusic.nValue = ClipRange(mus_volume, sliderMusic.nRangeLow, sliderMusic.nRangeHigh); - sliderSound.nValue = ClipRange(snd_fxvolume, sliderSound.nRangeLow, sliderSound.nRangeHigh); - bool3DAudio.at20 = snd_doppler; - boolCrosshair.at20 = cl_crosshair; - itemCycleShowWeapons.m_nFocus = cl_showweapon; - boolSlopeTilting.at20 = cl_slopetilting; - boolViewBobbing.at20 = cl_viewvbob; - boolViewSwaying.at20 = cl_viewhbob; - boolMessages.at20 = gGameMessageMgr.state; - menuOptionsOld.Add(&itemOptionsTitle, false); - menuOptionsOld.Add(&itemOption1, true); - menuOptionsOld.Add(&sliderDetail, false); - menuOptionsOld.Add(&sliderGamma, false); - menuOptionsOld.Add(&sliderMusic, false); - menuOptionsOld.Add(&sliderSound, false); - //menuOptionsOld.Add(&sliderCDAudio, false); - menuOptionsOld.Add(&bool3DAudio, false); - menuOptionsOld.Add(&boolCrosshair, false); - menuOptionsOld.Add(&itemCycleShowWeapons, false); - menuOptionsOld.Add(&boolSlopeTilting, false); - menuOptionsOld.Add(&boolViewBobbing, false); - menuOptionsOld.Add(&boolViewSwaying, false); - menuOptionsOld.Add(&itemOption2, false); - menuOptionsOld.Add(&itemChainParentalLock, false); - menuOptionsOld.Add(&itemBloodQAV, false); -} - -void SetupDifficultyMenu(void) -{ - menuDifficulty.Add(&itemDifficultyTitle, false); - menuDifficulty.Add(&itemDifficulty1, false); - menuDifficulty.Add(&itemDifficulty2, false); - menuDifficulty.Add(&itemDifficulty3, true); - menuDifficulty.Add(&itemDifficulty4, false); - menuDifficulty.Add(&itemDifficulty5, false); - menuDifficulty.Add(&itemBloodQAV, false); -} - -void SetupEpisodeMenu(void) -{ - menuEpisode.Add(&itemEpisodesTitle, false); - bool unk = false; - int height; - gMenuTextMgr.GetFontInfo(1, NULL, NULL, &height); - int j = 0; - for (int i = 0; i < 6; i++) - { - EPISODEINFO *pEpisode = &gEpisodeInfo[i]; - if (!pEpisode->bloodbath || gGameOptions.nGameType != 0) - { - if (j < gEpisodeCount) - { - CGameMenuItemChain7F2F0 *pEpisodeItem = &itemEpisodes[j]; - pEpisodeItem->m_nFont = 1; - pEpisodeItem->m_nX = 0; - pEpisodeItem->m_nWidth = 320; - pEpisodeItem->at20 = 1; - pEpisodeItem->m_pzText = pEpisode->at0; - pEpisodeItem->m_nY = 55+(height+8)*j; - pEpisodeItem->at34 = i; - if (!unk || j == 0) - { - pEpisodeItem = &itemEpisodes[j]; - pEpisodeItem->at24 = &menuDifficulty; - pEpisodeItem->at28 = 3; - } - else - { - pEpisodeItem->at24 = &menuSorry2; - pEpisodeItem->at28 = 1; - } - pEpisodeItem = &itemEpisodes[j]; - pEpisodeItem->bCanSelect = 1; - pEpisodeItem->bEnable = 1; - bool first = j == 0; - menuEpisode.Add(&itemEpisodes[j], first); - if (first) - SetupLevelMenuItem(j); - } - j++; - } - } - menuEpisode.Add(&itemBloodQAV, false); -} - -void SetupMainMenu(void) -{ - menuMain.Add(&itemMainTitle, false); - menuMain.Add(&itemMain1, true); - if (gGameOptions.nGameType > 0) - { - itemMain1.at24 = &menuNetStart; - itemMain1.at28 = 2; - } - else - { - itemMain1.at24 = &menuEpisode; - itemMain1.at28 = -1; - } - menuMain.Add(&itemMain2, false); - menuMain.Add(&itemMain3, false); - menuMain.Add(&itemMain4, false); - menuMain.Add(&itemMain5, false); - menuMain.Add(&itemMain6, false); - menuMain.Add(&itemMain7, false); - menuMain.Add(&itemBloodQAV, false); -} - -void SetupMainMenuWithSave(void) -{ - menuMainWithSave.Add(&itemMainSaveTitle, false); - menuMainWithSave.Add(&itemMainSave1, true); - if (gGameOptions.nGameType > 0) - { - itemMainSave1.at24 = &menuNetStart; - itemMainSave1.at28 = 2; - } - else - { - itemMainSave1.at24 = &menuEpisode; - itemMainSave1.at28 = -1; - } - menuMainWithSave.Add(&itemMainSave2, false); - menuMainWithSave.Add(&itemMainSave3, false); - menuMainWithSave.Add(&itemMainSave4, false); - menuMainWithSave.Add(&itemMainSave5, false); - menuMainWithSave.Add(&itemMainSave6, false); - menuMainWithSave.Add(&itemMainSave7, false); - menuMainWithSave.Add(&itemMainSave8, false); - menuMainWithSave.Add(&itemBloodQAV, false); -} - -void SetupNetStartMenu(void) -{ - bool oneEpisode = false; - menuNetStart.Add(&itemNetStartTitle, false); - menuNetStart.Add(&itemNetStart1, false); - for (int i = 0; i < (oneEpisode ? 1 : 6); i++) - { - EPISODEINFO *pEpisode = &gEpisodeInfo[i]; - if (i < gEpisodeCount) - itemNetStart2.Add(pEpisode->at0, i == 0); - } - menuNetStart.Add(&itemNetStart2, false); - menuNetStart.Add(&itemNetStart3, false); - menuNetStart.Add(&itemNetStart4, false); - menuNetStart.Add(&itemNetStart5, false); - menuNetStart.Add(&itemNetStart6, false); - menuNetStart.Add(&itemNetStart7, false); - menuNetStart.Add(&itemNetStart8, false); - menuNetStart.Add(&itemNetStart9, false); - menuNetStart.Add(&itemNetStart10, false); - menuNetStart.Add(&itemNetStart11, false); - menuNetStart.Add(&itemNetStart12, false); - itemNetStart1.SetTextIndex(1); - itemNetStart4.SetTextIndex(2); - itemNetStart5.SetTextIndex(0); - itemNetStart6.SetTextIndex(1); - itemNetStart7.SetTextIndex(1); - menuNetStart.Add(&itemBloodQAV, false); -} - -void SetupSaveGameMenu(void) -{ - menuSaveGame.Add(&itemSaveTitle, false); - menuSaveGame.Add(&itemSaveGame1, true); - menuSaveGame.Add(&itemSaveGame2, false); - menuSaveGame.Add(&itemSaveGame3, false); - menuSaveGame.Add(&itemSaveGame4, false); - menuSaveGame.Add(&itemSaveGame5, false); - menuSaveGame.Add(&itemSaveGame6, false); - menuSaveGame.Add(&itemSaveGame7, false); - menuSaveGame.Add(&itemSaveGame8, false); - menuSaveGame.Add(&itemSaveGame9, false); - menuSaveGame.Add(&itemSaveGame10, false); - menuSaveGame.Add(&itemSaveGamePic, false); - menuSaveGame.Add(&itemBloodQAV, false); - - itemSaveGame1.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[0], "")) - itemSaveGame1.at37 = 1; - - itemSaveGame2.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[1], "")) - itemSaveGame2.at37 = 1; - - itemSaveGame3.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[2], "")) - itemSaveGame3.at37 = 1; - - itemSaveGame4.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[3], "")) - itemSaveGame4.at37 = 1; - - itemSaveGame5.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[4], "")) - itemSaveGame5.at37 = 1; - - itemSaveGame6.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[5], "")) - itemSaveGame6.at37 = 1; - - itemSaveGame7.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[6], "")) - itemSaveGame7.at37 = 1; - - itemSaveGame8.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[7], "")) - itemSaveGame8.at37 = 1; - - itemSaveGame9.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[8], "")) - itemSaveGame9.at37 = 1; - - itemSaveGame10.at2c = &itemSaveGamePic; - if (!strcmp(strRestoreGameStrings[9], "")) - itemSaveGame10.at37 = 1; -} - -void SetupLoadGameMenu(void) -{ - menuLoadGame.Add(&itemLoadTitle, false); - menuLoadGame.Add(&itemLoadGame1, true); - menuLoadGame.Add(&itemLoadGame2, false); - menuLoadGame.Add(&itemLoadGame3, false); - menuLoadGame.Add(&itemLoadGame4, false); - menuLoadGame.Add(&itemLoadGame5, false); - menuLoadGame.Add(&itemLoadGame6, false); - menuLoadGame.Add(&itemLoadGame7, false); - menuLoadGame.Add(&itemLoadGame8, false); - menuLoadGame.Add(&itemLoadGame9, false); - menuLoadGame.Add(&itemLoadGame10, false); - menuLoadGame.Add(&itemLoadGamePic, false); - itemLoadGame1.at35 = 0; - itemLoadGame2.at35 = 0; - itemLoadGame3.at35 = 0; - itemLoadGame4.at35 = 0; - itemLoadGame5.at35 = 0; - itemLoadGame6.at35 = 0; - itemLoadGame7.at35 = 0; - itemLoadGame8.at35 = 0; - itemLoadGame9.at35 = 0; - itemLoadGame10.at35 = 0; - itemLoadGame1.at2c = &itemLoadGamePic; - itemLoadGame2.at2c = &itemLoadGamePic; - itemLoadGame3.at2c = &itemLoadGamePic; - itemLoadGame4.at2c = &itemLoadGamePic; - itemLoadGame5.at2c = &itemLoadGamePic; - itemLoadGame6.at2c = &itemLoadGamePic; - itemLoadGame7.at2c = &itemLoadGamePic; - itemLoadGame8.at2c = &itemLoadGamePic; - itemLoadGame9.at2c = &itemLoadGamePic; - itemLoadGame10.at2c = &itemLoadGamePic; - menuLoadGame.Add(&itemBloodQAV, false); -} - -void SetupSoundsMenu(void) -{ - itemSoundsMusic.nValue = ClipRange(mus_volume, itemSoundsMusic.nRangeLow, itemSoundsMusic.nRangeHigh); - itemSoundsSound.nValue = ClipRange(snd_fxvolume, itemSoundsSound.nRangeLow, itemSoundsSound.nRangeHigh); - menuSounds.Add(&itemSoundsTitle, false); - menuSounds.Add(&itemSoundsMusic, true); - menuSounds.Add(&itemSoundsSound, false); - //menuSounds.Add(&itemSoundsCDAudio, false); - menuSounds.Add(&itemSounds3DAudio, false); - menuSounds.Add(&itemBloodQAV, false); -} - -void SetupQuitMenu(void) -{ - menuQuit.Add(&itemQuitTitle, false); - menuQuit.Add(&itemQuitText1, false); - menuQuit.Add(&itemQuitYesNo, true); - menuQuit.Add(&itemBloodQAV, false); - - menuRestart.Add(&itemRestartTitle, false); - menuRestart.Add(&itemRestartText1, false); - menuRestart.Add(&itemRestartYesNo, true); - menuRestart.Add(&itemBloodQAV, false); -} - -void SetupHelpOrderMenu(void) -{ - menuOrder.Add(&itemHelp4QAV, true); - menuOrder.Add(&itemHelp5QAV, false); - menuOrder.Add(&itemHelp3QAV, false); - menuOrder.Add(&itemHelp3BQAV, false); - itemHelp4QAV.bEnable = 1; - itemHelp4QAV.bNoDraw = 1; - itemHelp5QAV.bEnable = 1; - itemHelp5QAV.bNoDraw = 1; - itemHelp3QAV.bEnable = 1; - itemHelp3QAV.bNoDraw = 1; - itemHelp3BQAV.bEnable = 1; - itemHelp3BQAV.bNoDraw = 1; -} - -void SetupCreditsMenu(void) -{ - menuCredits.Add(&itemCreditsQAV, true); - itemCreditsQAV.bEnable = 1; - itemCreditsQAV.bNoDraw = 1; -} - -void SetupParentalLockMenu(void) -{ - itemParentalLockToggle.at20 = gbAdultContent; - strcpy(itemParentalLockPassword.at20, gzAdultPassword); - menuParentalLock.Add(&itemParentalLockTitle, false); - menuParentalLock.Add(&itemParentalLockToggle, true); - menuParentalLock.Add(&itemParentalLockPassword, false); - menuParentalLock.Add(&itemBloodQAV, false); -} - -void SetupSorry3Menu(void) -{ - menuPlayOnline.Add(&unk_26E06C, false); - menuPlayOnline.Add(&unk_26E090, true); - menuPlayOnline.Add(&unk_26E0E8, false); - menuPlayOnline.Add(&unk_26E140, false); - menuPlayOnline.Add(&unk_26E198, false); - menuPlayOnline.Add(&unk_26E1F0, false); - menuPlayOnline.Add(&unk_26E248, false); - menuPlayOnline.Add(&itemBloodQAV, false); -} - -void SetupSorryMenu(void) -{ - menuSorry.Add(&itemSorryPicCycle, true); - menuSorry.Add(&itemSorryText1, false); - menuSorry.Add(&itemSorryText3, false); - menuSorry.Add(&itemBloodQAV, false); -} - -void SetupSorry2Menu(void) -{ - menuSorry2.Add(&itemSorryPicCycle, true); - menuSorry2.Add(&itemSorry2Text1, false); - menuSorry2.Add(&itemSorry2Text2, false); - menuSorry2.Add(&itemSorry2Text3, false); - menuSorry2.Add(&itemBloodQAV, false); -} - -void SetupOptionsMenu(void) -{ - menuOptions.Add(&itemOptionsTitle, false); - menuOptions.Add(&itemOptionsChainGame, true); - menuOptions.Add(&itemOptionsChainDisplay, false); - menuOptions.Add(&itemOptionsChainSound, false); - menuOptions.Add(&itemOptionsChainPlayer, false); - menuOptions.Add(&itemOptionsChainControl, false); - //menuOptions.Add(&itemOptionsChainOld, false); - menuOptions.Add(&itemBloodQAV, false); - - menuOptionsGame.Add(&itemOptionsGameTitle, false); - menuOptionsGame.Add(&itemOptionsGameBoolShowPlayerNames, true); - menuOptionsGame.Add(&itemOptionsGameShowWeapons, false); - menuOptionsGame.Add(&itemOptionsGameBoolSlopeTilting, false); - menuOptionsGame.Add(&itemOptionsGameBoolViewBobbing, false); - menuOptionsGame.Add(&itemOptionsGameBoolViewSwaying, false); - menuOptionsGame.Add(&itemOptionsGameBoolAutoAim, false); - menuOptionsGame.Add(&itemOptionsGameWeaponSwitch, false); - - ////////////////////// - if (gGameOptions.nGameType == 0) { - menuOptionsGame.Add(&itemOptionsGameBoolWeaponsV10X, false); - } - ///////////////////// - - //menuOptionsGame.Add(&itemOptionsGameChainParentalLock, false); - menuOptionsGame.Add(&itemBloodQAV, false); - itemOptionsGameShowWeapons.m_nFocus = cl_showweapon; - itemOptionsGameBoolSlopeTilting.at20 = cl_slopetilting; - itemOptionsGameBoolViewBobbing.at20 = cl_viewvbob; - itemOptionsGameBoolViewSwaying.at20 = cl_viewhbob; - itemOptionsGameBoolAutoAim.m_nFocus = cl_autoaim; - itemOptionsGameWeaponSwitch.m_nFocus = (cl_weaponswitch&1) ? ((cl_weaponswitch&2) ? 1 : 2) : 0; - - /////// - itemOptionsGameBoolWeaponsV10X.at20 = gWeaponsV10x; - /////// - - menuOptionsDisplay.Add(&itemOptionsDisplayTitle, false); - menuOptionsDisplay.Add(&itemOptionsDisplayColor, true); - menuOptionsDisplay.Add(&itemOptionsDisplayMode, false); - menuOptionsDisplay.Add(&itemOptionsDisplayBoolCrosshair, false); - menuOptionsDisplay.Add(&itemOptionsDisplayBoolCenterHoriz, false); - menuOptionsDisplay.Add(&itemOptionsDisplayBoolLevelStats, false); - menuOptionsDisplay.Add(&itemOptionsDisplayBoolPowerupDuration, false); - menuOptionsDisplay.Add(&itemOptionsDisplayBoolShowMapTitle, false); - menuOptionsDisplay.Add(&itemOptionsDisplayBoolMessages, false); - menuOptionsDisplay.Add(&itemOptionsDisplayBoolWidescreen, false); - menuOptionsDisplay.Add(&itemOptionsDisplayFOV, false); -#ifdef USE_OPENGL - menuOptionsDisplay.Add(&itemOptionsDisplayPolymost, false); -#endif - menuOptionsDisplay.Add(&itemBloodQAV, false); - itemOptionsDisplayBoolCrosshair.at20 = cl_crosshair; - itemOptionsDisplayBoolCenterHoriz.at20 = r_horizcenter; - itemOptionsDisplayBoolLevelStats.at20 = hud_stats; - itemOptionsDisplayBoolPowerupDuration.at20 = hud_powerupduration; - itemOptionsDisplayBoolShowMapTitle.at20 = hud_showmapname; - itemOptionsDisplayBoolMessages.at20 = hud_messages; - itemOptionsDisplayBoolWidescreen.at20 = r_usenewaspect; - - menuOptionsDisplayMode.Add(&itemOptionsDisplayModeTitle, false); - menuOptionsDisplayMode.Add(&itemOptionsDisplayModeResolution, true); - // prepare video setup - for (int i = 0; i < validmodecnt; ++i) - { - int j; - for (j = 0; j < gResolutionNum; ++j) - { - if (validmode[i].xdim == gResolution[j].xdim && validmode[i].ydim == gResolution[j].ydim) - { - gResolution[j].flags |= validmode[i].fs ? RES_FS : RES_WIN; - Bsnprintf(gResolution[j].name, MAXRESOLUTIONSTRINGLENGTH, "%d x %d%s", gResolution[j].xdim, gResolution[j].ydim, (gResolution[j].flags & RES_FS) ? "" : "Win"); - gResolutionName[j] = gResolution[j].name; - if (validmode[i].bpp > gResolution[j].bppmax) - gResolution[j].bppmax = validmode[i].bpp; - break; - } - } - - if (j == gResolutionNum) // no match found - { - gResolution[j].xdim = validmode[i].xdim; - gResolution[j].ydim = validmode[i].ydim; - gResolution[j].bppmax = validmode[i].bpp; - gResolution[j].flags = validmode[i].fs ? RES_FS : RES_WIN; - Bsnprintf(gResolution[j].name, MAXRESOLUTIONSTRINGLENGTH, "%d x %d%s", gResolution[j].xdim, gResolution[j].ydim, (gResolution[j].flags & RES_FS) ? "" : "Win"); - gResolutionName[j] = gResolution[j].name; - ++gResolutionNum; - } - } - itemOptionsDisplayModeResolution.SetTextArray(gResolutionName, gResolutionNum, 0); -#ifdef USE_OPENGL - menuOptionsDisplayMode.Add(&itemOptionsDisplayModeRenderer, false); -#endif - menuOptionsDisplayMode.Add(&itemOptionsDisplayModeFullscreen, false); - menuOptionsDisplayMode.Add(&itemOptionsDisplayModeVSync, false); - menuOptionsDisplayMode.Add(&itemOptionsDisplayModeApply, false); - menuOptionsDisplayMode.Add(&itemBloodQAV, false); - -#ifdef USE_OPENGL - itemOptionsDisplayModeRenderer.pPreDrawCallback = PreDrawVideoModeMenu; -#endif - itemOptionsDisplayModeFullscreen.pPreDrawCallback = PreDrawVideoModeMenu; - - menuOptionsDisplayColor.Add(&itemOptionsDisplayColorTitle, false); - menuOptionsDisplayColor.Add(&itemOptionsDisplayColorGamma, true); - menuOptionsDisplayColor.Add(&itemOptionsDisplayColorContrast, false); - menuOptionsDisplayColor.Add(&itemOptionsDisplayColorBrightness, false); - menuOptionsDisplayColor.Add(&itemOptionsDisplayColorVisibility, false); - menuOptionsDisplayColor.Add(&itemOptionsDisplayColorReset, false); - menuOptionsDisplayColor.Add(&itemBloodQAV, false); - - itemOptionsDisplayColorContrast.pPreDrawCallback = PreDrawDisplayColor; - itemOptionsDisplayColorBrightness.pPreDrawCallback = PreDrawDisplayColor; - -#ifdef USE_OPENGL - menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymostTitle, false); - //menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymostTextureMode, true); - //menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymostAnisotropy, false); - menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymostTrueColorTextures, true); - menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymostPreloadCache, false); - menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymostDetailTex, false); - menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymostGlowTex, false); - menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymost3DModels, false); - menuOptionsDisplayPolymost.Add(&itemOptionsDisplayPolymostDeliriumBlur, false); - menuOptionsDisplayPolymost.Add(&itemBloodQAV, false); - - itemOptionsDisplayPolymostPreloadCache.pPreDrawCallback = PreDrawDisplayPolymost; - itemOptionsDisplayPolymostDetailTex.pPreDrawCallback = PreDrawDisplayPolymost; - itemOptionsDisplayPolymostGlowTex.pPreDrawCallback = PreDrawDisplayPolymost; -#endif - - menuOptionsSound.Add(&itemOptionsSoundTitle, false); - menuOptionsSound.Add(&itemOptionsSoundSoundToggle, true); - menuOptionsSound.Add(&itemOptionsSoundMusicToggle, false); - menuOptionsSound.Add(&itemOptionsSound3DToggle, false); - menuOptionsSound.Add(&itemOptionsSoundSoundVolume, false); - menuOptionsSound.Add(&itemOptionsSoundMusicVolume, false); - menuOptionsSound.Add(&itemOptionsSoundSampleRate, false); - menuOptionsSound.Add(&itemOptionsSoundNumVoices, false); - menuOptionsSound.Add(&itemOptionsSoundCDToggle, false); - menuOptionsSound.Add(&itemOptionsSoundMusicDevice, false); - menuOptionsSound.Add(&itemOptionsSoundApplyChanges, false); - menuOptionsSound.Add(&itemBloodQAV, false); - - menuOptionsPlayer.Add(&itemOptionsPlayerTitle, false); - //menuOptionsPlayer.Add(&itemOptionsPlayerName, true); - menuOptionsPlayer.Add(&itemBloodQAV, false); - - menuOptionsControl.Add(&itemOptionsControlTitle, false); - menuOptionsControl.Add(&itemOptionsControlKeyboard, true); - menuOptionsControl.Add(&itemOptionsControlMouse, false); - menuOptionsControl.Add(&itemBloodQAV, false); - - menuOptionsControlKeyboard.Add(&itemOptionsControlKeyboardTitle, false); - menuOptionsControlKeyboard.Add(&itemOptionsControlKeyboardList, true); - menuOptionsControlKeyboard.Add(&itemOptionsControlKeyboardReset, false); - menuOptionsControlKeyboard.Add(&itemOptionsControlKeyboardResetClassic, false); - menuOptionsControlKeyboard.Add(&itemBloodQAV, false); - - menuOptionsControlMouse.Add(&itemOptionsControlMouseTitle, false); -// menuOptionsControlMouse.Add(&itemOptionsControlMouseButton, true); - menuOptionsControlMouse.Add(&itemOptionsControlMouseSensitivity, false); - menuOptionsControlMouse.Add(&itemOptionsControlMouseAimFlipped, false); - menuOptionsControlMouse.Add(&itemOptionsControlMouseFilterInput, false); - menuOptionsControlMouse.Add(&itemOptionsControlMouseAimMode, false); - menuOptionsControlMouse.Add(&itemOptionsControlMouseVerticalAim, false); - menuOptionsControlMouse.Add(&itemOptionsControlMouseXScale, false); - menuOptionsControlMouse.Add(&itemOptionsControlMouseYScale, false); - //menuOptionsControlMouse.Add(&itemOptionsControlMouseDigitalUp, false); - //menuOptionsControlMouse.Add(&itemOptionsControlMouseDigitalDown, false); - //menuOptionsControlMouse.Add(&itemOptionsControlMouseDigitalLeft, false); - //menuOptionsControlMouse.Add(&itemOptionsControlMouseDigitalRight, false); - //menuOptionsControlMouse.Add(&itemBloodQAV, false); - - //itemOptionsControlMouseDigitalUp.SetTextArray(pzGamefuncsStrings, NUMGAMEFUNCTIONS+1, 0); - //itemOptionsControlMouseDigitalDown.SetTextArray(pzGamefuncsStrings, NUMGAMEFUNCTIONS+1, 0); - //itemOptionsControlMouseDigitalLeft.SetTextArray(pzGamefuncsStrings, NUMGAMEFUNCTIONS+1, 0); - //itemOptionsControlMouseDigitalRight.SetTextArray(pzGamefuncsStrings, NUMGAMEFUNCTIONS+1, 0); - - itemOptionsControlMouseVerticalAim.pPreDrawCallback = PreDrawControlMouse; - - menuOptionsControlMouseButtonAssignment.Add(&itemOptionsControlMouseTitle, false); - int y = 60; - for (int i = 0; i < MENUMOUSEFUNCTIONS; i++) - { - pItemOptionsControlMouseButton[i] = new CGameMenuItemZCycle(MenuMouseNames[i], 3, 66, y, 180, 0, SetMouseButton, pzGamefuncsStrings, NUMGAMEFUNCTIONS+1, 0, true); - dassert(pItemOptionsControlMouseButton[i] != NULL); - menuOptionsControlMouseButtonAssignment.Add(pItemOptionsControlMouseButton[i], i == 0); - y += 10; - } - menuOptionsControlMouseButtonAssignment.Add(&itemBloodQAV, false); -} - -void SetupMenus(void) -{ - // prepare gamefuncs and keys - pzGamefuncsStrings[0] = MenuGameFuncNone; - nGamefuncsValues[0] = -1; - int k = 1; - for (int i = 0; i < NUMGAMEFUNCTIONS; ++i) - { - MenuGameFuncs[i] = buttonMap.GetButtonName(i); - MenuGameFuncs[i].Substitute('_', ' '); - - if (MenuGameFuncs[i][0] != '\0') - { - pzGamefuncsStrings[k] = MenuGameFuncs[i]; - nGamefuncsValues[k] = i; - ++k; - } - } - - nGamefuncsNum = k; - - SetupLoadingScreen(); - SetupKeyListMenu(); - SetupMessagesMenu(); - SetupControlsMenu(); - SetupSaveGameMenu(); - SetupLoadGameMenu(); - SetupOptionsOldMenu(); - SetupCreditsMenu(); - SetupHelpOrderMenu(); - SetupSoundsMenu(); - SetupDifficultyMenu(); - SetupEpisodeMenu(); - SetupMainMenu(); - SetupMainMenuWithSave(); - SetupNetStartMenu(); - SetupQuitMenu(); - SetupParentalLockMenu(); - SetupSorryMenu(); - SetupSorry2Menu(); - SetupSorry3Menu(); - - SetupOptionsMenu(); - SetupNetworkMenu(); -} - -void UpdateNetworkMenus(void) -{ - if (gGameOptions.nGameType > 0) - { - itemMain1.at24 = &menuNetStart; - itemMain1.at28 = 2; - } - else - { - itemMain1.at24 = &menuEpisode; - itemMain1.at28 = -1; - } - if (gGameOptions.nGameType > 0) - { - itemMainSave1.at24 = &menuNetStart; - itemMainSave1.at28 = 2; - } - else - { - itemMainSave1.at24 = &menuEpisode; - itemMainSave1.at28 = -1; - } -} - -void SetDoppler(CGameMenuItemZBool *pItem) -{ - snd_doppler = pItem->at20; -} - -void SetCrosshair(CGameMenuItemZBool *pItem) -{ - cl_crosshair = pItem->at20; -} - -void SetCenterHoriz(CGameMenuItemZBool *pItem) -{ - r_horizcenter = pItem->at20; -} - -void ConfigureKeys(CGameMenuItemChain*) -{ - GUICapture |= 2; -} - -void ResetKeys(CGameMenuItemChain *) -{ - CONFIG_SetDefaultKeys("demolition/defbinds.txt"); -} - -void ResetKeysClassic(CGameMenuItemChain *) -{ - CONFIG_SetDefaultKeys("demolition/origbinds.txt"); -} //// void SetWeaponsV10X(CGameMenuItemZBool* pItem) @@ -1417,74 +100,6 @@ void SetWeaponsV10X(CGameMenuItemZBool* pItem) } //// -void SetShowPlayerNames(CGameMenuItemZBool *pItem) -{ - cl_idplayers = pItem->at20; -} - -void SetShowWeapons(CGameMenuItemZCycle *pItem) -{ - cl_showweapon = pItem->m_nFocus; -} - -void SetSlopeTilting(CGameMenuItemZBool *pItem) -{ - cl_slopetilting = pItem->at20; -} - -void SetViewBobbing(CGameMenuItemZBool *pItem) -{ - cl_viewvbob = pItem->at20; -} - -void SetViewSwaying(CGameMenuItemZBool *pItem) -{ - cl_viewhbob = pItem->at20; -} - -void SetDetail(CGameMenuItemSlider *pItem) -{ - gDetail = pItem->nValue; -} - -void SetGamma(CGameMenuItemSlider *pItem) -{ - gGamma = pItem->nValue; - scrSetGamma(gGamma); -} - -void SetMusicVol(CGameMenuItemSlider *pItem) -{ - mus_volume = pItem->nValue; -} - -void SetSoundVol(CGameMenuItemSlider *pItem) -{ - snd_fxvolume = pItem->nValue; - sndSetFXVolume(pItem->nValue); -} - -void SetCDVol(CGameMenuItemSlider *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - // NUKE-TODO: -} - -void SetMessages(CGameMenuItemZBool *pItem) -{ - hud_messages = pItem->at20; -} - -void SetMouseSensitivity(CGameMenuItemSliderFloat *pItem) -{ - in_mousesensitivity = pItem->fValue; -} - -void SetMouseAimFlipped(CGameMenuItemZBool *pItem) -{ - in_mouseflip = pItem->at20; -} - void SetTurnSpeed(CGameMenuItemSlider *pItem) { gTurnSpeed = pItem->nValue; @@ -1500,494 +115,6 @@ void SetAutoAim(CGameMenuItemZCycle *pItem) } } -void SetLevelStats(CGameMenuItemZBool *pItem) -{ - hud_stats = pItem->at20; -} - -void SetPowerupDuration(CGameMenuItemZBool* pItem) -{ - hud_powerupduration = pItem->at20; -} - -void SetShowMapTitle(CGameMenuItemZBool* pItem) -{ - hud_showmapname = pItem->at20; -} - -void SetWeaponSwitch(CGameMenuItemZCycle *pItem) -{ - - cl_weaponswitch = cl_weaponswitch & ~(1|2); - switch (pItem->m_nFocus) - { - case 0: - break; - case 1: - cl_weaponswitch = cl_weaponswitch | 2; - fallthrough__; - case 2: - default: - cl_weaponswitch = cl_weaponswitch | 1; - break; - } - if (!gDemo.at0 && !gDemo.at1) - { - gProfile[myconnectindex].nWeaponSwitch = cl_weaponswitch; - netBroadcastPlayerInfo(myconnectindex); - } -} - -extern bool gStartNewGame; - -void SetDifficultyAndStart(CGameMenuItemChain *pItem) -{ - gGameOptions.nDifficulty = pItem->at30; - gSkill = pItem->at30; - gGameOptions.nLevel = 0; - if (gDemo.at1) - gDemo.StopPlayback(); - gStartNewGame = true; - gCheatMgr.sub_5BCF4(); - gGameMenuMgr.Deactivate(); -} - -void SetVideoModeOld(CGameMenuItemChain *pItem) -{ - if (pItem->at30 == validmodecnt) - { - ScreenMode = 0; - ScreenWidth = 640; - ScreenHeight = 480; - } - else - { - ScreenMode = 0; - ScreenWidth = validmode[pItem->at30].xdim; - ScreenHeight = validmode[pItem->at30].ydim; - } - scrSetGameMode(ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP); - scrSetDac(); - viewResizeView(gViewSize); -} - -void SetVideoMode(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - resolution_t p = { xres, yres, fullscreen, bpp, 0 }; - int32_t prend = videoGetRenderMode(); - int32_t pvsync = vid_vsync; - - int32_t nResolution = itemOptionsDisplayModeResolution.m_nFocus; - resolution_t n = { gResolution[nResolution].xdim, gResolution[nResolution].ydim, - (gResolution[nResolution].flags & RES_FS) ? itemOptionsDisplayModeFullscreen.at20 : 0, - (nRendererValues[itemOptionsDisplayModeRenderer.m_nFocus] == REND_CLASSIC) ? 8 : gResolution[nResolution].bppmax, 0 }; - int32_t UNUSED(nrend) = nRendererValues[itemOptionsDisplayModeRenderer.m_nFocus]; - int32_t nvsync = nVSyncValues[itemOptionsDisplayModeVSync.m_nFocus]; - - if (videoSetGameMode(n.flags, n.xdim, n.ydim, n.bppmax, upscalefactor) < 0) - { - if (videoSetGameMode(p.flags, p.xdim, p.ydim, p.bppmax, upscalefactor) < 0) - { - videoSetRenderMode(prend); - ThrowError("Failed restoring old video mode."); - } - else - { - onvideomodechange(p.bppmax > 8); - vid_vsync = videoSetVsync(pvsync); - } - } - else onvideomodechange(n.bppmax > 8); - - viewResizeView(gViewSize); - vid_vsync = videoSetVsync(nvsync); - ScreenMode = fullscreen; - ScreenWidth = xres; - ScreenHeight = yres; - ScreenBPP = bpp; -} - -void SetWidescreen(CGameMenuItemZBool *pItem) -{ - r_usenewaspect = pItem->at20; -} - -void SetFOV(CGameMenuItemSlider *pItem) -{ - r_fov = pItem->nValue; -} - -void SetupVideoModeMenu(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - for (int i = 0; i < gResolutionNum; i++) - { - if (ScreenWidth == gResolution[i].xdim && ScreenHeight == gResolution[i].ydim) - { - itemOptionsDisplayModeResolution.m_nFocus = i; - break; - } - } - itemOptionsDisplayModeFullscreen.at20 = ScreenMode; -#ifdef USE_OPENGL - for (int i = 0; i < 2; i++) - { - if (videoGetRenderMode() == nRendererValues[i]) - { - itemOptionsDisplayModeRenderer.m_nFocus = i; - break; - } - } -#endif - for (int i = 0; i < 3; i++) - { - if (vid_vsync == nVSyncValues[i]) - { - itemOptionsDisplayModeVSync.m_nFocus = i; - break; - } - } -} - -void PreDrawVideoModeMenu(CGameMenuItem *pItem) -{ - if (pItem == &itemOptionsDisplayModeFullscreen) - pItem->bEnable = !!(gResolution[itemOptionsDisplayModeResolution.m_nFocus].flags & RES_FS); -#ifdef USE_OPENGL - else if (pItem == &itemOptionsDisplayModeRenderer) - pItem->bEnable = gResolution[itemOptionsDisplayModeResolution.m_nFocus].bppmax > 8; -#endif -} - -void UpdateVideoColorMenu(CGameMenuItemSliderFloat *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - vid_gamma = itemOptionsDisplayColorGamma.fValue; - vid_contrast = itemOptionsDisplayColorContrast.fValue; - vid_brightness = itemOptionsDisplayColorBrightness.fValue; - r_ambientlight = itemOptionsDisplayColorVisibility.fValue; -} - -void PreDrawDisplayColor(CGameMenuItem *pItem) -{ - if (pItem == &itemOptionsDisplayColorContrast) - pItem->bEnable = 1; - else if (pItem == &itemOptionsDisplayColorBrightness) - pItem->bEnable = 1; -} - -void ResetVideoColor(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - vid_gamma = 1.f; - vid_contrast = 1.f; - vid_brightness = 0.f; - r_ambientlight = 1.f; -} - -#ifdef USE_OPENGL -void SetupVideoPolymostMenu(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - itemOptionsDisplayPolymostTextureMode.m_nFocus = 0; - for (int i = 0; i < 2; i++) - { - if (nTextureModeValues[i] == hw_texfilter) - { - itemOptionsDisplayPolymostTextureMode.m_nFocus = i; - break; - } - } - itemOptionsDisplayPolymostAnisotropy.m_nFocus = 0; - for (int i = 0; i < 6; i++) - { - if (nAnisotropyValues[i] == hw_anisotropy) - { - itemOptionsDisplayPolymostAnisotropy.m_nFocus = i; - break; - } - } - itemOptionsDisplayPolymostTrueColorTextures.at20 = hw_hightile; - itemOptionsDisplayPolymostPreloadCache.at20 = r_precache; - itemOptionsDisplayPolymostDetailTex.at20 = hw_detailmapping; - itemOptionsDisplayPolymostGlowTex.at20 = hw_glowmapping; - itemOptionsDisplayPolymost3DModels.at20 = hw_models; - itemOptionsDisplayPolymostDeliriumBlur.at20 = gDeliriumBlur; -} - -void UpdateTextureMode(CGameMenuItemZCycle *pItem) -{ - hw_texfilter = nTextureModeValues[pItem->m_nFocus]; - gltexapplyprops(); -} - -void UpdateAnisotropy(CGameMenuItemZCycle *pItem) -{ - hw_anisotropy = nAnisotropyValues[pItem->m_nFocus]; - gltexapplyprops(); -} - -void UpdateTrueColorTextures(CGameMenuItemZBool *pItem) -{ - hw_hightile = pItem->at20; -} -#endif - -void DoModeChange(void) -{ - videoResetMode(); - if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor)) - OSD_Printf("restartvid: Reset failed...\n"); - onvideomodechange(ScreenBPP > 8); -} - -#ifdef USE_OPENGL -void UpdatePreloadCache(CGameMenuItemZBool *pItem) -{ - r_precache = pItem->at20; -} - -void UpdateDetailTex(CGameMenuItemZBool *pItem) -{ - hw_detailmapping = pItem->at20; -} - -void UpdateGlowTex(CGameMenuItemZBool *pItem) -{ - hw_glowmapping = pItem->at20; -} - -void Update3DModels(CGameMenuItemZBool *pItem) -{ - hw_models = pItem->at20; -} - -void UpdateDeliriumBlur(CGameMenuItemZBool *pItem) -{ - gDeliriumBlur = pItem->at20; -} - -void PreDrawDisplayPolymost(CGameMenuItem *pItem) -{ - if (pItem == &itemOptionsDisplayPolymostPreloadCache) - pItem->bEnable = hw_hightile; - else if (pItem == &itemOptionsDisplayPolymostDetailTex) - pItem->bEnable = hw_hightile; - else if (pItem == &itemOptionsDisplayPolymostGlowTex) - pItem->bEnable = hw_hightile; -} -#endif - -void UpdateSoundToggle(CGameMenuItemZBool *pItem) -{ - snd_enabled = pItem->at20; - if (!SoundEnabled()) - FX_StopAllSounds(); -} - -void UpdateMusicToggle(CGameMenuItemZBool *pItem) -{ - mus_enabled = pItem->at20; - if (!MusicEnabled()) - sndStopSong(); - else - { - if (gGameStarted || gDemo.at1) - sndPlaySong("*", gGameOptions.zLevelSong, true); - } -} - -void Update3DToggle(CGameMenuItemZBool *pItem) -{ - snd_doppler = pItem->at20; -} - -void UpdateCDToggle(CGameMenuItemZBool *pItem) -{ - mus_redbook = pItem->at20; - if (gGameStarted || gDemo.at1) - levelTryPlayMusicOrNothing(gGameOptions.nEpisode, gGameOptions.nLevel); -} - -void UpdateSoundVolume(CGameMenuItemSlider *pItem) -{ - sndSetFXVolume(pItem->nValue); -} - -void UpdateMusicVolume(CGameMenuItemSlider *pItem) -{ - mus_volume = pItem->nValue; -} - -void UpdateSoundRate(CGameMenuItemZCycle *pItem) -{ - UNREFERENCED_PARAMETER(pItem); -} - -void UpdateNumVoices(CGameMenuItemSlider *pItem) -{ - UNREFERENCED_PARAMETER(pItem); -} - -void UpdateMusicDevice(CGameMenuItemZCycle *pItem) -{ - UNREFERENCED_PARAMETER(pItem); -} - -void SetSound(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - snd_mixrate = nSoundRateValues[itemOptionsSoundSampleRate.m_nFocus]; - snd_numvoices = itemOptionsSoundNumVoices.nValue; - mus_device = nMusicDeviceValues[itemOptionsSoundMusicDevice.m_nFocus]; - sfxTerm(); - sndTerm(); - - sndInit(); - sfxInit(); - - if (mus_enabled && (gGameStarted || gDemo.at1)) - sndPlaySong("*", gGameOptions.zLevelSong, true); -} - -void PreDrawSound(CGameMenuItem *pItem) -{ - UNREFERENCED_PARAMETER(pItem); -} - -void SetupOptionsSound(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - itemOptionsSoundSoundToggle.at20 = snd_enabled; - itemOptionsSoundMusicToggle.at20 = mus_enabled; - itemOptionsSound3DToggle.at20 = snd_doppler; - itemOptionsSoundCDToggle.at20 = mus_redbook; - itemOptionsSoundSampleRate.m_nFocus = 0; - for (int i = 0; i < 3; i++) - { - if (nSoundRateValues[i] == snd_mixrate) - { - itemOptionsSoundSampleRate.m_nFocus = i; - break; - } - } - itemOptionsSoundNumVoices.nValue = snd_numvoices; - itemOptionsSoundMusicDevice.m_nFocus = 0; - for (int i = 0; i < ARRAY_SIZE(nMusicDeviceValues); i++) - { - if (nMusicDeviceValues[i] == MusicDevice) - { - itemOptionsSoundMusicDevice.m_nFocus = i; - break; - } - } -} - -void UpdatePlayerName(CGameMenuItemZEdit *pItem, CGameMenuEvent *pEvent) -{ - UNREFERENCED_PARAMETER(pItem); - if (pEvent->at0 == kMenuEventEnter) - netBroadcastPlayerInfo(myconnectindex); -} - -void SetMouseFilterInput(CGameMenuItemZBool *pItem) -{ - in_mousesmoothing = pItem->at20; -} - -void SetMouseAimMode(CGameMenuItemZBool *pItem) -{ - in_aimmode = pItem->at20; -} - -void SetMouseVerticalAim(CGameMenuItemZBool *pItem) -{ - in_mousemode = pItem->at20; -} - -void SetMouseXScale(CGameMenuItemSlider *pItem) -{ - in_mousescalex = pItem->nValue; -} - -void SetMouseYScale(CGameMenuItemSlider *pItem) -{ - in_mousescaley = pItem->nValue; -} - -void SetMouseDigitalAxis(CGameMenuItemZCycle *pItem) -{ -#if 0 - if (pItem == &itemOptionsControlMouseDigitalUp) - { - MouseDigitalFunctions[1][0] = nGamefuncsValues[pItem->m_nFocus]; - CONTROL_MapDigitalAxis(1, MouseDigitalFunctions[1][0], 0, controldevice_mouse); - } - else if (pItem == &itemOptionsControlMouseDigitalDown) - { - MouseDigitalFunctions[1][1] = nGamefuncsValues[pItem->m_nFocus]; - CONTROL_MapDigitalAxis(1, MouseDigitalFunctions[1][1], 1, controldevice_mouse); - } - else if (pItem == &itemOptionsControlMouseDigitalLeft) - { - MouseDigitalFunctions[0][0] = nGamefuncsValues[pItem->m_nFocus]; - CONTROL_MapDigitalAxis(0, MouseDigitalFunctions[0][0], 0, controldevice_mouse); - } - else if (pItem == &itemOptionsControlMouseDigitalRight) - { - MouseDigitalFunctions[0][1] = nGamefuncsValues[pItem->m_nFocus]; - CONTROL_MapDigitalAxis(0, MouseDigitalFunctions[0][1], 1, controldevice_mouse); - } -#endif -} - -void SetupMouseMenu(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); -#if 0 - static CGameMenuItemZCycle *pMouseDigitalAxis[4] = { - &itemOptionsControlMouseDigitalLeft, - &itemOptionsControlMouseDigitalRight, - &itemOptionsControlMouseDigitalUp, - &itemOptionsControlMouseDigitalDown - }; - for (int i = 0; i < ARRAY_SSIZE(pMouseDigitalAxis); i++) - { - CGameMenuItemZCycle *pItem = pMouseDigitalAxis[i]; - pItem->m_nFocus = 0; - for (int j = 0; j < NUMGAMEFUNCTIONS+1; j++) - { - if (nGamefuncsValues[j] == MouseDigitalFunctions[i>>1][i&1]) - { - pItem->m_nFocus = j; - break; - } - } - } -#endif - itemOptionsControlMouseAimFlipped.at20 = in_mouseflip; - itemOptionsControlMouseFilterInput.at20 = in_mousesmoothing; - itemOptionsControlMouseAimMode.at20 = in_aimmode; - itemOptionsControlMouseVerticalAim.at20 = g_MyAimMode; -} - -void PreDrawControlMouse(CGameMenuItem *pItem) -{ - if (pItem == &itemOptionsControlMouseVerticalAim) - pItem->bEnable = !in_aimmode; -} - -void SetMouseButton(CGameMenuItemZCycle *pItem) -{ -} - -void SetupMouseButtonMenu(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - // This functionality no longer exists as a separate item. -} - void SetupNetworkMenu(void) { sprintf(zNetPortBuffer, "%d", gNetPort); @@ -2025,7 +152,7 @@ void SetupNetworkJoinMenu(CGameMenuItemChain *pItem) void NetworkHostGame(CGameMenuItemChain *pItem) { UNREFERENCED_PARAMETER(pItem); - sndStopSong(); + Mus_Stop(); FX_StopAllSounds(); UpdateDacs(0, true); gNetPlayers = itemNetworkHostPlayerNum.nValue; @@ -2041,7 +168,7 @@ void NetworkHostGame(CGameMenuItemChain *pItem) void NetworkJoinGame(CGameMenuItemChain *pItem) { UNREFERENCED_PARAMETER(pItem); - sndStopSong(); + Mus_Stop(); FX_StopAllSounds(); UpdateDacs(0, true); strcpy(gNetAddress, zNetAddressBuffer); @@ -2054,135 +181,6 @@ void NetworkJoinGame(CGameMenuItemChain *pItem) gQuitGame = gRestartGame = true; } -void SaveGameProcess(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); -} - -void TenProcess(CGameMenuItem7EA1C *pItem) -{ - UNREFERENCED_PARAMETER(pItem); -} - -short gQuickLoadSlot = -1; -short gQuickSaveSlot = -1; - -void SaveGame(CGameMenuItemZEditBitmap *pItem, CGameMenuEvent *event) -{ - char strSaveGameName[BMAX_PATH]; - int nSlot = pItem->at28; - if (gGameOptions.nGameType > 0 || !gGameStarted) - return; - if (event->at0 != 6/* || strSaveGameName[0]*/) - { - gGameMenuMgr.Deactivate(); - return; - } - snprintf(strSaveGameName, BMAX_PATH, "%sgame00%02d.sav", M_GetSavegamesPath().GetChars(), nSlot); - strcpy(gGameOptions.szUserGameName, strRestoreGameStrings[nSlot]); - sprintf(gGameOptions.szSaveGameName, "%s", strSaveGameName); - gGameOptions.nSaveGameSlot = nSlot; - viewLoadingScreen(2518, "Saving", "Saving Your Game", strRestoreGameStrings[nSlot]); - videoNextPage(); - gSaveGameNum = nSlot; - LoadSave::SaveGame(strSaveGameName); - gQuickSaveSlot = nSlot; - gGameMenuMgr.Deactivate(); -} - -void QuickSaveGame(void) -{ - char strSaveGameName[BMAX_PATH]; - if (gGameOptions.nGameType > 0 || !gGameStarted) - return; - /*if (strSaveGameName[0]) - { - gGameMenuMgr.Deactivate(); - return; - }*/ - snprintf(strSaveGameName, BMAX_PATH, "%sgame00%02d.sav", M_GetSavegamesPath().GetChars(), gQuickSaveSlot); - strcpy(gGameOptions.szUserGameName, strRestoreGameStrings[gQuickSaveSlot]); - sprintf(gGameOptions.szSaveGameName, "%s", strSaveGameName); - gGameOptions.nSaveGameSlot = gQuickSaveSlot; - viewLoadingScreen(2518, "Saving", "Saving Your Game", strRestoreGameStrings[gQuickSaveSlot]); - videoNextPage(); - LoadSave::SaveGame(strSaveGameName); - gGameOptions.picEntry = gSavedOffset; - gSaveGameOptions[gQuickSaveSlot] = gGameOptions; - UpdateSavedInfo(gQuickSaveSlot); - gGameMenuMgr.Deactivate(); -} - -void LoadGame(CGameMenuItemZEditBitmap *pItem, CGameMenuEvent *event) -{ - UNREFERENCED_PARAMETER(event); - char strLoadGameName[BMAX_PATH]; - int nSlot = pItem->at28; - if (gGameOptions.nGameType > 0) - return; - snprintf(strLoadGameName, BMAX_PATH, "%sgame00%02d.sav", M_GetSavegamesPath().GetChars(), nSlot); - if (!FileExists(strLoadGameName)) - return; - viewLoadingScreen(2518, "Loading", "Loading Saved Game", strRestoreGameStrings[nSlot]); - videoNextPage(); - LoadSave::LoadGame(strLoadGameName); - gGameMenuMgr.Deactivate(); - gQuickLoadSlot = nSlot; -} - -void QuickLoadGame(void) -{ - char strLoadGameName[BMAX_PATH]; - if (gGameOptions.nGameType > 0) - return; - snprintf(strLoadGameName, BMAX_PATH, "%sgame00%02d.sav", M_GetSavegamesPath().GetChars(), gQuickLoadSlot); - if (!FileExists(strLoadGameName)) - return; - viewLoadingScreen(2518, "Loading", "Loading Saved Game", strRestoreGameStrings[gQuickLoadSlot]); - videoNextPage(); - LoadSave::LoadGame(strLoadGameName); - gGameMenuMgr.Deactivate(); -} - -void SetupLevelMenuItem(int nEpisode) -{ - dassert(nEpisode >= 0 && nEpisode < gEpisodeCount); - itemNetStart3.SetTextArray(zLevelNames[nEpisode], gEpisodeInfo[nEpisode].nLevels, 0); -} - -void SetupNetLevels(CGameMenuItemZCycle *pItem) -{ - SetupLevelMenuItem(pItem->m_nFocus); -} - -void StartNetGame(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - gPacketStartGame.gameType = itemNetStart1.m_nFocus+1; - if (gPacketStartGame.gameType == 0) - gPacketStartGame.gameType = 2; - gPacketStartGame.episodeId = itemNetStart2.m_nFocus; - gPacketStartGame.levelId = itemNetStart3.m_nFocus; - gPacketStartGame.difficulty = itemNetStart4.m_nFocus; - gPacketStartGame.monsterSettings = itemNetStart5.m_nFocus; - gPacketStartGame.weaponSettings = itemNetStart6.m_nFocus; - gPacketStartGame.itemSettings = itemNetStart7.m_nFocus; - gPacketStartGame.respawnSettings = 0; - gPacketStartGame.bFriendlyFire = itemNetStart8.at20; - gPacketStartGame.bKeepKeysOnRespawn = itemNetStart9.at20; - //// - gPacketStartGame.weaponsV10x = itemNetStart10.at20; - //// - gPacketStartGame.unk = 0; - gPacketStartGame.userMapName[0] = 0; - strncpy(gPacketStartGame.userMapName, itemNetStart11.at20, 13); - gPacketStartGame.userMapName[12] = 0; - gPacketStartGame.userMap = gPacketStartGame.userMapName[0] != 0; - - netBroadcastNewGame(); - gStartNewGame = 1; - gGameMenuMgr.Deactivate(); -} void Restart(CGameMenuItemChain *pItem) { @@ -2197,77 +195,7 @@ void Restart(CGameMenuItemChain *pItem) gGameMenuMgr.Deactivate(); } -void Quit(CGameMenuItemChain *pItem) -{ - UNREFERENCED_PARAMETER(pItem); - if (gGameOptions.nGameType == 0 || numplayers == 1) - gQuitGame = true; - else - gQuitRequest = 1; - gGameMenuMgr.Deactivate(); -} -void SetParentalLock(CGameMenuItemZBool *pItem) -{ - if (!pItem->at20) - { - pItem->at20 = true; - pItem->Draw(); - if (strcmp(itemParentalLockPassword.at20, "")) - { - itemParentalLockPassword.pMenu->FocusNextItem(); - itemParentalLockPassword.at32 = 0; - itemParentalLockPassword.at37 = 1; - itemParentalLockPassword.at5f = pItem; - itemParentalLockPassword.at29[0] = 0; - return; - } - else - { - itemParentalLockPassword.at20[0] = 0; - pItem->Draw(); - gbAdultContent = false; - } - } - else - gbAdultContent = true; - // NUKE-TODO: CONFIG_WriteAdultMode(); -} -void MenuSetupEpisodeInfo(void) -{ - memset(zEpisodeNames, 0, sizeof(zEpisodeNames)); - memset(zLevelNames, 0, sizeof(zLevelNames)); - for (int i = 0; i < 6; i++) - { - if (i < gEpisodeCount) - { - EPISODEINFO *pEpisode = &gEpisodeInfo[i]; - zEpisodeNames[i] = pEpisode->at0; - for (int j = 0; j < 16; j++) - { - if (j < pEpisode->nLevels) - { - zLevelNames[i][j] = pEpisode->at28[j].at90; - } - } - } - } -} +#endif -void drawLoadingScreen(void) -{ - char buffer[80]; - if (gGameOptions.nGameType == 0) - { - if (gDemo.at1) - sprintf(buffer, "Loading Demo"); - else - sprintf(buffer, "Loading Level"); - } - else - sprintf(buffer, "%s", zNetGameTypes[gGameOptions.nGameType-1]); - viewLoadingScreen(2049, buffer, levelGetTitle(), NULL); -} - -END_BLD_NS diff --git a/source/blood/src/menu.h b/source/blood/src/menu.h deleted file mode 100644 index 786095574..000000000 --- a/source/blood/src/menu.h +++ /dev/null @@ -1,63 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2010-2019 EDuke32 developers and contributors -Copyright (C) 2019 Nuke.YKT - -This file is part of NBlood. - -NBlood is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- -#pragma once -#include "gamemenu.h" - -BEGIN_BLD_NS - -extern CGameMenu menuMain; -extern CGameMenu menuMainWithSave; -extern CGameMenu menuNetMain; -extern CGameMenu menuNetStart; -extern CGameMenu menuEpisode; -extern CGameMenu menuDifficulty; -extern CGameMenu menuOptionsOld; -extern CGameMenu menuControls; -extern CGameMenu menuMessages; -extern CGameMenu menuKeys; -extern CGameMenu menuSaveGame; -extern CGameMenu menuLoadGame; -extern CGameMenu menuLoading; -extern CGameMenu menuSounds; -extern CGameMenu menuQuit; -extern CGameMenu menuRestart; -extern CGameMenu menuCredits; -extern CGameMenu menuOrder; -extern CGameMenu menuPlayOnline; -extern CGameMenu menuParentalLock; -extern CGameMenu menuSorry; -extern CGameMenu menuSorry2; - -extern CGameMenu menuOptions; -extern CGameMenu menuOptionsSound; -extern CGameMenu menuOptionsDisplayMode; -extern short gQuickLoadSlot; -extern short gQuickSaveSlot; -extern char strRestoreGameStrings[][16]; -void drawLoadingScreen(void); -void SetupMenus(void); -void UpdateNetworkMenus(void); -void QuickSaveGame(void); -void QuickLoadGame(void); - -END_BLD_NS diff --git a/source/blood/src/menus.h b/source/blood/src/menus.h deleted file mode 100644 index b7792a9c7..000000000 --- a/source/blood/src/menus.h +++ /dev/null @@ -1,537 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2016 EDuke32 developers and contributors - -This file is part of EDuke32. - -EDuke32 is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- - -#ifndef menus_h_ -#define menus_h_ - -#include "compat.h" -#include "cache1d.h" -#include "pragmas.h" -#include "common.h" -#include "blood.h" - -BEGIN_BLD_NS - -#if defined EDUKE32_TOUCH_DEVICES -# define EDUKE32_SIMPLE_MENU -# define EDUKE32_ANDROID_MENU -#endif - -// #define EDUKE32_SIMPLE_MENU - -enum MenuIndex_t { - MENU_NULL = INT32_MIN, // sentinel for "do nothing" - MENU_CLOSE = -2, // sentinel for "close the menu"/"no menu" - MENU_PREVIOUS = -1, // sentinel for "go to previous menu" - MENU_MAIN = 0, - MENU_MAIN_INGAME = 50, - MENU_EPISODE = 100, - MENU_USERMAP = 101, - MENU_NEWGAMECUSTOM = 102, - MENU_NEWGAMECUSTOMSUB = 103, - MENU_SKILL = 110, - MENU_GAMESETUP = 200, - MENU_OPTIONS = 202, - MENU_VIDEOSETUP = 203, - MENU_KEYBOARDSETUP = 204, - MENU_MOUSESETUP = 205, - MENU_JOYSTICKSETUP = 206, - MENU_JOYSTICKBTNS = 207, - MENU_JOYSTICKAXES = 208, - MENU_KEYBOARDKEYS = 209, - MENU_MOUSEBTNS = 210, - MENU_MOUSEADVANCED = 212, - MENU_JOYSTICKAXIS = 213, - MENU_TOUCHSETUP = 214, - MENU_TOUCHSENS = 215, - MENU_TOUCHBUTTONS = 216, - MENU_CONTROLS = 220, - MENU_POLYMOST = 230, - MENU_COLCORR = 231, - MENU_COLCORR_INGAME = 232, - MENU_SCREENSETUP = 233, - MENU_DISPLAYSETUP = 234, - MENU_POLYMER = 240, - MENU_LOAD = 300, - MENU_SAVE = 350, - MENU_STORY = 400, - MENU_F1HELP = 401, - MENU_QUIT = 500, - MENU_QUITTOTITLE = 501, - MENU_QUIT_INGAME = 502, - MENU_NETSETUP = 600, - MENU_NETWAITMASTER = 601, - MENU_NETWAITVOTES = 603, - MENU_SOUND = 700, - MENU_SOUND_INGAME = 701, - MENU_ADVSOUND = 702, - MENU_SAVESETUP = 750, - MENU_SAVECLEANVERIFY = 751, - MENU_RESETSTATSVERIFY = 752, - MENU_CHEATS = 800, - MENU_CHEATENTRY = 801, - MENU_CHEAT_WARP = 802, - MENU_CHEAT_SKILL = 803, - MENU_CREDITS = 990, - MENU_CREDITS2 = 991, - MENU_CREDITS3 = 992, - MENU_CREDITS4 = 993, - MENU_CREDITS5 = 994, - MENU_LOADVERIFY = 1000, - MENU_LOADDELVERIFY = 1100, - MENU_NEWVERIFY = 1500, - MENU_SAVEVERIFY = 2000, - MENU_SAVEDELVERIFY = 2100, - MENU_COLCORRRESETVERIFY = 2200, - MENU_KEYSRESETVERIFY = 2201, - MENU_KEYSCLASSICVERIFY = 2202, - MENU_JOYSTANDARDVERIFY = 2203, - MENU_JOYPROVERIFY = 2204, - MENU_JOYCLEARVERIFY = 2205, - MENU_ADULTPASSWORD = 10001, - MENU_RESETPLAYER = 15000, - MENU_BUYDUKE = 20000, - MENU_NETWORK = 20001, - MENU_PLAYER = 20002, - MENU_MACROS = 20004, - MENU_NETHOST = 20010, - MENU_NETOPTIONS = 20011, - MENU_NETUSERMAP = 20012, - MENU_NETJOIN = 20020, -}; - - - -typedef int32_t MenuID_t; - - -typedef enum MenuAnimationType_t -{ // Note: This enum is for logical categories, not visual types. - MA_None, - MA_Return, - MA_Advance, -} MenuAnimationType_t; - -// a subset of screentext parameters, restricted because menus require accessibility -typedef struct MenuFont_t -{ -// int32_t xspace, yline; - vec2_t emptychar, between; - int32_t zoom; - int32_t cursorLeftPosition, cursorCenterPosition, cursorScale; - int32_t textflags; - int16_t tilenum; - // selected shade glows, deselected shade is used by Blood, disabled shade is used by SW - int8_t shade_deselected, shade_disabled; - uint8_t pal; - uint8_t pal_selected, pal_deselected, pal_disabled; - uint8_t pal_selected_right, pal_deselected_right, pal_disabled_right; - - int32_t get_yline() const { return mulscale16(emptychar.y, zoom); } -} MenuFont_t; - - - -typedef enum MenuEntryType_t -{ - Dummy, - Link, - Option, - Custom2Col, - RangeInt32, - RangeFloat, -#ifdef MENU_ENABLE_RANGEDOUBLE - RangeDouble, -#endif - String, - Spacer, -} MenuEntryType_t; - -typedef struct MenuEntryFormat_t -{ - int32_t marginBottom; - int32_t indent; - int32_t width; // 0: center, >0: width of the label column (left-aligned options), <0: -width of everything (right-aligned) -} MenuEntryFormat_t; - - -typedef struct MenuMenuFormat_t -{ - vec2_t pos; - int32_t bottomcutoff; // >0: the bottom edge of the menu before automatic scrolling kicks in, <0: -total height for vertical justification -} MenuMenuFormat_t; - -typedef struct MenuLink_t -{ - // traits - MenuID_t linkID; - MenuAnimationType_t animation; -} MenuLink_t; -typedef struct MenuOptionSet_t -{ - // traits - char const **optionNames; - int32_t *optionValues; // If NULL, the identity of currentOption is assumed. - - // pop-up list appearance - MenuMenuFormat_t *menuFormat; - MenuEntryFormat_t *entryFormat; - MenuFont_t *font; - - // traits - int32_t numOptions; - - // pop-up list state - int32_t currentEntry; - int32_t scrollPos; - - // appearance - uint8_t features; // bit 1 = disable left/right arrows, bit 2 = disable list - - int32_t getMarginBottom() const { return mulscale16(entryFormat->marginBottom, font->zoom); } - int32_t getIndent() const { return mulscale16(entryFormat->indent, font->zoom); } -} MenuOptionSet_t; -typedef struct MenuOption_t -{ - // appearance - MenuFont_t *font; - - // traits - MenuOptionSet_t *options; // so that common sets such as Yes/No, On/Off can be reused - - // effect - int32_t *data; - - // state - int32_t currentOption; -} MenuOption_t; -typedef struct MenuCustom2Col_t -{ - // effect - uint8_t *column[2]; - char const **key; - - // appearance - MenuFont_t *font; - - // effect - size_t numvalid; - - // appearance - int32_t columnWidth; - - // state - int8_t screenOpen; -} MenuCustom2Col_t; - -enum MenuRangeFlags_t -{ - DisplayTypeInteger = 1, - DisplayTypePercent = 2, - DisplayTypeNormalizedDecimal = 3, - DisplayTypeMask = (1<<0)|(1<<1), - - EnforceIntervals = 1<<7, -}; -typedef struct MenuRangeInt32_t -{ - // effect - int32_t *variable; - - // appearance - MenuFont_t *font; - - // traits - int32_t min; - int32_t max; - int32_t onehundredpercent; // 0 implies max - int32_t steps; - - uint8_t flags; -} MenuRangeInt32_t; -typedef struct MenuRangeFloat_t -{ - // effect - float *variable; - - // appearance - MenuFont_t *font; - - // traits - float min; - float max; - float onehundredpercent; // 0 implies 1.0 - int32_t steps; - - uint8_t flags; -} MenuRangeFloat_t; -#ifdef MENU_ENABLE_RANGEDOUBLE -typedef struct MenuRangeDouble_t -{ - // effect - double *variable; - - // appearance - MenuFont_t *font; - - // traits - double min; - double max; - double onehundredpercent; // 0 implies 1.0 - int32_t steps; - - uint8_t flags; -} MenuRangeDouble_t; -#endif -typedef struct MenuString_t -{ - // state - char* editfield; - - // effect - char* variable; - - // appearance - MenuFont_t *font; - - // effect - int32_t bufsize; - int32_t flags; -} MenuString_t; -typedef struct MenuSpacer_t -{ - int32_t height; -} MenuSpacer_t; - -// For internal use only. -enum MenuEntryFlags_t -{ - MEF_Disabled = 1<<0, - MEF_LookDisabled = 1<<1, - MEF_Hidden = 1<<2, -}; - -typedef struct MenuEntry_t -{ - // traits - const char *name; - - // appearance - MenuFont_t *font; - MenuEntryFormat_t *format; - - void *entry; - MenuEntryType_t type; - - // state - int32_t flags; - int32_t ytop, ybottom; - - int32_t getMarginBottom() const { return mulscale16(format->marginBottom, font->zoom); } - int32_t getIndent() const { return mulscale16(format->indent, font->zoom); } - int32_t getHeight() const - { - return type == Spacer ? mulscale16(((MenuSpacer_t *)entry)->height, font->zoom) : font->get_yline(); - } -} MenuEntry_t; - - -typedef enum MenuType_t -{ - Menu, - Panel, - Verify, - Message, - TextForm, - FileSelect, -} MenuType_t; - -typedef struct MenuMenu_t -{ - const char *title; - - MenuMenuFormat_t *format; - - MenuEntry_t **entrylist; - int32_t numEntries; - - // state - int32_t currentEntry, currentColumn; - int32_t scrollPos; -} MenuMenu_t; -typedef struct MenuPanel_t -{ - const char *title; - - MenuID_t previousID; - MenuAnimationType_t previousAnimation; - MenuID_t nextID; - MenuAnimationType_t nextAnimation; -} MenuPanel_t; -typedef struct MenuVerify_t -{ - vec2_t cursorpos; - - MenuID_t linkID; - MenuAnimationType_t animation; -} MenuVerify_t; -typedef struct MenuMessage_t -{ - vec2_t cursorpos; - - MenuID_t linkID; - MenuAnimationType_t animation; -} MenuMessage_t; -enum MenuTextFormFlags_t -{ - MTF_Password = 1<<0, -}; -typedef struct MenuTextForm_t -{ - // state - char *input; - - // traits - const char *instructions; - int32_t bufsize; - uint8_t flags; -} MenuTextForm_t; -typedef struct MenuFileSelect_t -{ - const char *title; - - // appearance - MenuMenuFormat_t *format[2]; - MenuFont_t *font[2]; - - // traits - const char * startdir; - const char *pattern; - char *destination; - - // state - //CACHE1D_FIND_REC *findhigh[2]; - int32_t scrollPos[2]; - - // appearance - int32_t marginBottom[2]; - - // state - //fnlist_t fnlist; - int32_t currentList; - - int32_t getMarginBottom(size_t index) const { return mulscale16(marginBottom[index], font[index]->zoom); } -} MenuFileSelect_t; - -typedef struct Menu_t -{ - void *object; - MenuID_t menuID; - MenuID_t parentID; - MenuAnimationType_t parentAnimation; - MenuType_t type; -} Menu_t; - -typedef struct MenuAnimation_t -{ - int32_t(*out)(struct MenuAnimation_t *); - int32_t(*in)(struct MenuAnimation_t *); - - Menu_t *previous; - Menu_t *current; - - int32_t start; - int32_t length; -} MenuAnimation_t; - -extern MenuAnimation_t m_animation; - -extern MenuID_t g_currentMenu; -extern Menu_t *m_currentMenu; - -extern int32_t g_quitDeadline; -extern int32_t voting; -int Menu_Change(MenuID_t cm); -void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype); -int32_t Menu_IsTextInput(Menu_t *cm); -int G_CheckPlayerColor(int color); -void Menu_Init(void); -void Menu_Open(uint8_t playerID); -void Menu_Close(uint8_t playerID); -void M_DisplayMenus(void); - -extern MenuFont_t MF_Redfont, MF_Bluefont, MF_Minifont; - -#define M_MOUSETIMEOUT 210 -extern int32_t m_mouselastactivity; - -#if defined EDUKE32_TOUCH_DEVICES -# define MOUSEALPHA 0 -# define CURSORALPHA (255/3) -# define MOUSEACTIVECONDITIONAL(condition) (condition) -# define MOUSEWATCHPOINTCONDITIONAL(condition) (condition) -#else -extern int32_t m_mousewake_watchpoint, m_menuchange_watchpoint; -// alpha increments of 3 --> 255 / 3 = 85 --> round up to power of 2 --> 128 --> divide by 2 --> 64 alphatabs required -// use 16 anyway :P -#if 0 -# define MOUSEUSEALPHA (videoGetRenderMode() != REND_CLASSIC || numalphatabs >= 15) -# define MOUSEALPHA (MOUSEUSEALPHA ? clamp(((int32_t) totalclock - m_mouselastactivity - 90)*3, 0, 255) : 0) -# define CURSORALPHA (MOUSEUSEALPHA ? clamp(((int32_t) totalclock - m_mouselastactivity - 90)*2 + (255/3), (255/3), 255) : 255/3) -# define MOUSEACTIVECONDITION (totalclock - m_mouselastactivity < M_MOUSETIMEOUT) -# define MOUSEACTIVECONDITIONAL(condition) (MOUSEACTIVECONDITION && (condition)) -# define MOUSEINACTIVECONDITIONAL(condition) ((gInputMode != kInputMenu || !MOUSEACTIVECONDITION) && (condition)) -# define MOUSEWATCHPOINTCONDITIONAL(condition) ((condition) || m_mousewake_watchpoint || m_menuchange_watchpoint == 3) -#endif -#endif - -#define MAXMENUGAMEPLAYENTRIES 7 - -enum MenuGameplayEntryFlags -{ - MGE_Locked = 1u<<0u, - MGE_Hidden = 1u<<1u, - MGE_UserContent = 1u<<2u, -}; - -typedef struct MenuGameplayEntry -{ - char name[64]; - uint8_t flags; - - bool isValid() const { return name[0] != '\0'; } -} MenuGameplayEntry; - -typedef struct MenuGameplayStemEntry -{ - MenuGameplayEntry entry; - MenuGameplayEntry subentries[MAXMENUGAMEPLAYENTRIES]; -} MenuGameplayStemEntry; - -extern MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES]; - -extern MenuEntry_t ME_NEWGAMECUSTOMENTRIES[MAXMENUGAMEPLAYENTRIES]; -extern MenuEntry_t ME_NEWGAMECUSTOMSUBENTRIES[MAXMENUGAMEPLAYENTRIES][MAXMENUGAMEPLAYENTRIES]; - -END_BLD_NS - -#endif diff --git a/source/blood/src/messages.cpp b/source/blood/src/messages.cpp index f69cb5c96..c93c0f13a 100644 --- a/source/blood/src/messages.cpp +++ b/source/blood/src/messages.cpp @@ -36,11 +36,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "globals.h" #include "levels.h" #include "loadsave.h" -#include "menu.h" +#include "gamemenu.h" #include "messages.h" #include "network.h" #include "player.h" #include "view.h" +#include "gstrings.h" BEGIN_BLD_NS @@ -53,32 +54,22 @@ void sub_5A928(void) buttonMap.ClearButton(i); } -void sub_5A944(int key) -{ - auto binding = Bindings.GetBind(key); - if (binding) - { - auto index = buttonMap.FindButtonIndex(binding); - if (index >= 0) buttonMap.ClearButton(index); - } -} - void SetGodMode(bool god) { playerSetGodMode(gMe, god); if (gMe->godMode) - viewSetMessage("You are immortal."); + viewSetMessage(GStrings("TXTB_GODMODE")); else - viewSetMessage("You are mortal."); + viewSetMessage(GStrings("TXTB_NOTGODMODE")); } void SetClipMode(bool noclip) { gNoClip = noclip; if (gNoClip) - viewSetMessage("Unclipped movement."); + viewSetMessage(GStrings("TXTB_NOCLIP")); else - viewSetMessage("Normal movement."); + viewSetMessage(GStrings("TXTB_NOCLIPOFF")); } void packStuff(PLAYER *pPlayer) @@ -103,13 +94,13 @@ void SetAmmo(bool stat) { for (int i = 0; i < 12; i++) gMe->ammoCount[i] = gAmmoInfo[i].max; - viewSetMessage("You have full ammo."); + viewSetMessage(GStrings("TXTB_FULLAMMO")); } else { for (int i = 0; i < 12; i++) gMe->ammoCount[i] = 0; - viewSetMessage("You have no ammo."); + viewSetMessage(GStrings("TXTB_NOAMMO")); } } @@ -121,7 +112,7 @@ void SetWeapons(bool stat) } SetAmmo(stat); if (stat) - viewSetMessage("You have all weapons."); + viewSetMessage(GStrings("TXTB_ALLWEAP")); else { if (!VanillaMode()) @@ -131,7 +122,7 @@ void SetWeapons(bool stat) gMe->curWeapon = 0; gMe->nextWeapon = 1; } - viewSetMessage("You have no weapons."); + viewSetMessage(GStrings("TXTB_NOWEAP")); } } @@ -140,12 +131,12 @@ void SetToys(bool stat) if (stat) { packStuff(gMe); - viewSetMessage("Your inventory is full."); + viewSetMessage(GStrings("TXTB_FULLINV")); } else { packClear(gMe); - viewSetMessage("Your inventory is empty."); + viewSetMessage(GStrings("TXTB_NOINV")); } } @@ -154,12 +145,12 @@ void SetArmor(bool stat) int nAmount; if (stat) { - viewSetMessage("You have full armor."); + viewSetMessage(GStrings("TXTB_FULLARM")); nAmount = 3200; } else { - viewSetMessage("You have no armor."); + viewSetMessage(GStrings("TXTB_NOARM")); nAmount = 0; } for (int i = 0; i < 3; i++) @@ -171,27 +162,27 @@ void SetKeys(bool stat) for (int i = 1; i <= 6; i++) gMe->hasKey[i] = stat; if (stat) - viewSetMessage("You have all keys."); + viewSetMessage(GStrings("TXTB_ALLKEYS")); else - viewSetMessage("You have no keys."); + viewSetMessage(GStrings("TXTB_NOKEYS")); } void SetInfiniteAmmo(bool stat) { gInfiniteAmmo = stat; if (gInfiniteAmmo) - viewSetMessage("You have infinite ammo."); + viewSetMessage(GStrings("TXTB_INFAMMO")); else - viewSetMessage("You have limited ammo."); + viewSetMessage(GStrings("TXTB_LIMAMMO")); } void SetMap(bool stat) { gFullMap = stat; if (gFullMap) - viewSetMessage("You have the map."); + viewSetMessage(GStrings("TXTB_ALLMAP")); else - viewSetMessage("You have no map."); + viewSetMessage(GStrings("TXTB_NOALLMAP")); } void SetWooMode(bool stat) @@ -221,7 +212,7 @@ void ToggleBoots(void) { if (powerupCheck(gMe, kPwUpJumpBoots)) { - viewSetMessage("You have no Jumping Boots."); + viewSetMessage(GStrings("TXTB_NOJBOOTS")); if (!VanillaMode()) { gMe->pwUpTime[kPwUpJumpBoots] = 0; @@ -231,7 +222,7 @@ void ToggleBoots(void) } else { - viewSetMessage("You have the Jumping Boots."); + viewSetMessage(GStrings("TXTB_JBOOTS")); if (!VanillaMode()) gMe->pwUpTime[kPwUpJumpBoots] = gPowerUpInfo[kPwUpJumpBoots].bonusTime; powerupActivate(gMe, kPwUpJumpBoots); @@ -242,14 +233,14 @@ void ToggleInvisibility(void) { if (powerupCheck(gMe, kPwUpShadowCloak)) { - viewSetMessage("You are visible."); + viewSetMessage(GStrings("TXTB_VISIBLE")); if (!VanillaMode()) gMe->pwUpTime[kPwUpShadowCloak] = 0; powerupDeactivate(gMe, kPwUpShadowCloak); } else { - viewSetMessage("You are invisible."); + viewSetMessage(GStrings("TXTB_INVISIBLE")); powerupActivate(gMe, kPwUpShadowCloak); } } @@ -258,14 +249,14 @@ void ToggleInvulnerability(void) { if (powerupCheck(gMe, kPwUpDeathMask)) { - viewSetMessage("You are vulnerable."); + viewSetMessage(GStrings("TXTB_VULN")); if (!VanillaMode()) gMe->pwUpTime[kPwUpDeathMask] = 0; powerupDeactivate(gMe, kPwUpDeathMask); } else { - viewSetMessage("You are invulnerable."); + viewSetMessage(GStrings("TXTB_INVULN")); powerupActivate(gMe, kPwUpDeathMask); } } @@ -274,14 +265,14 @@ void ToggleDelirium(void) { if (powerupCheck(gMe, kPwUpDeliriumShroom)) { - viewSetMessage("You are not delirious."); + viewSetMessage(GStrings("TXTB_NODELIR")); if (!VanillaMode()) gMe->pwUpTime[kPwUpDeliriumShroom] = 0; powerupDeactivate(gMe, kPwUpDeliriumShroom); } else { - viewSetMessage("You are delirious."); + viewSetMessage(GStrings("TXTB_DELIR")); powerupActivate(gMe, kPwUpDeliriumShroom); } } @@ -335,7 +326,7 @@ void CGameMessageMgr::SetState(char state) void CGameMessageMgr::Add(const char *pText, char a2, const int pal, const MESSAGE_PRIORITY priority) { - if (a2 && messageFlags) + if (a2 && messageFlags && hud_messages == 1) // add only if messages are enabled and in native format { messageStruct *pMessage = &messages[nextMessagesIndex]; strncpy(pMessage->text, pText, kMaxMessageTextLength-1); @@ -383,7 +374,7 @@ void CGameMessageMgr::Display(void) if (gViewMode == 3) { int height; - gMenuTextMgr.GetFontInfo(nFont, pMessage->text, &height, NULL); + viewGetFontInfo(nFont, pMessage->text, &height, NULL); if (x+height > gViewX1S) viewUpdatePages(); } @@ -428,7 +419,7 @@ void CGameMessageMgr::Display(void) if (gViewMode == 3) { int height; - gMenuTextMgr.GetFontInfo(nFont, pMessage->text, &height, NULL); + viewGetFontInfo(nFont, pMessage->text, &height, NULL); if (x+height > gViewX1S) viewUpdatePages(); } @@ -590,58 +581,6 @@ void CPlayerMsg::Send(void) void CPlayerMsg::ProcessKeys(void) { if (inputState.GetKeyStatus(sc_Escape)) Term(); -#if 0 - int key = inputState.keyGetScan(); - int ch; - if (key != 0) - { - bool ctrl = (inputState.CtrlPressed()); - bool shift = (inputState.ShiftPressed()); - switch (key) - { - case sc_Escape: - Term(); - break; - case sc_F1: - case sc_F2: - case sc_F3: - case sc_F4: - case sc_F5: - case sc_F6: - case sc_F7: - case sc_F8: - case sc_F9: - case sc_F10: - buttonMap.ClearButton(gamefunc_See_Chase_View); - Set(*CombatMacros[key-sc_F1]); - Send(); - inputState.ClearKeyStatus(key); - break; - case sc_BackSpace: - if (ctrl) - Clear(); - else - DelChar(); - break; - case sc_Enter: - case sc_kpad_Enter: - if (gCheatMgr.Check(text)) - Term(); - else - Send(); - break; - default: - if (key < 128) - { - ch = shift ? g_keyAsciiTableShift[key] : g_keyAsciiTable[key]; - if (ch) - AddChar(ch); - } - break; - } - sub_5A944(key); - } -#endif } bool CPlayerMsg::IsWhitespaceOnly(const char * const pzString) @@ -781,19 +720,19 @@ void CCheatMgr::Process(CCheatMgr::CHEATCODE nCheatCode, char* pzArgs) break; case kCheatKevorkian: actDamageSprite(gMe->nSprite, gMe->pSprite, DAMAGE_TYPE_2, 8000); - viewSetMessage("Kevorkian approves."); + viewSetMessage(GStrings("TXTB_KEVORKIAN")); break; case kCheatMcGee: { if (!gMe->pXSprite->burnTime) evPost(gMe->nSprite, 3, 0, kCallbackFXFlameLick); actBurnSprite(actSpriteIdToOwnerId(gMe->nSprite), gMe->pXSprite, 2400); - viewSetMessage("You're fired!"); + viewSetMessage(GStrings("TXTB_FIRED")); break; } case kCheatEdmark: actDamageSprite(gMe->nSprite, gMe->pSprite, DAMAGE_TYPE_3, 8000); - viewSetMessage("Ahhh...those were the days."); + viewSetMessage(GStrings("TXTB_THEDAYS")); break; case kCheatKrueger: { @@ -802,7 +741,7 @@ void CCheatMgr::Process(CCheatMgr::CHEATCODE nCheatCode, char* pzArgs) if (!gMe->pXSprite->burnTime) evPost(gMe->nSprite, 3, 0, kCallbackFXFlameLick); actBurnSprite(actSpriteIdToOwnerId(gMe->nSprite), gMe->pXSprite, 2400); - viewSetMessage("Flame retardant!"); + viewSetMessage(GStrings("TXTB_RETARD")); break; } case kCheatSterno: @@ -820,7 +759,7 @@ void CCheatMgr::Process(CCheatMgr::CHEATCODE nCheatCode, char* pzArgs) case kCheatClarice: if (!VanillaMode()) { - viewSetMessage("You have half armor."); + viewSetMessage(GStrings("TXTB_HALFARMOR")); for (int i = 0; i < 3; i++) gMe->armor[i] = 1600; } diff --git a/source/blood/src/network.cpp b/source/blood/src/network.cpp index 1e6242d79..6da2b56ad 100644 --- a/source/blood/src/network.cpp +++ b/source/blood/src/network.cpp @@ -33,7 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "controls.h" #include "globals.h" #include "network.h" -#include "menu.h" +#include "gamemenu.h" #include "player.h" #include "seq.h" #include "sound.h" @@ -542,7 +542,7 @@ void netGetPackets(void) gStartNewGame = 1; break; case 255: - inputState.SetKeyStatus(sc_Escape, 1); + inputState.SetKeyStatus(sc_Escape); break; } } @@ -1007,11 +1007,13 @@ void netInitialize(bool bConsole) while (numplayers < gNetPlayers) { handleevents(); +#if 0 if (quitevent) { netServerDisconnect(); QuitGame(); } +#endif if (!bConsole && inputState.GetKeyStatus(sc_Escape)) { netServerDisconnect(); @@ -1168,11 +1170,13 @@ void netInitialize(bool bConsole) while (bWaitServer) { handleevents(); +#if 0 if (quitevent) { netClientDisconnect(); QuitGame(); } +#endif if (!bConsole && inputState.GetKeyStatus(sc_Escape)) { netClientDisconnect(); diff --git a/source/blood/src/osdcmd.cpp b/source/blood/src/osdcmd.cpp index c7dd70d98..b8d38f114 100644 --- a/source/blood/src/osdcmd.cpp +++ b/source/blood/src/osdcmd.cpp @@ -47,53 +47,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -static int osdcmd_changelevel(osdcmdptr_t parm) -{ - int32_t volume,level; - char *p; - - if (parm->numparms != 2) return OSDCMD_SHOWHELP; - - volume = strtol(parm->parms[0], &p, 10) - 1; - if (p[0]) return OSDCMD_SHOWHELP; - level = strtol(parm->parms[1], &p, 10) - 1; - if (p[0]) return OSDCMD_SHOWHELP; - - if (volume < 0) return OSDCMD_SHOWHELP; - if (level < 0) return OSDCMD_SHOWHELP; - - if (volume >= 6) - { - OSD_Printf("changelevel: invalid volume number (range 1-%d)\n",6); - return OSDCMD_OK; - } - - if (level >= gEpisodeInfo[volume].nLevels) - { - OSD_Printf("changelevel: invalid level number\n"); - return OSDCMD_SHOWHELP; - } - - if (gDemo.at1) - gDemo.StopPlayback(); - - if (numplayers > 1) - { - gPacketStartGame.episodeId = volume; - gPacketStartGame.levelId = level; - netBroadcastNewGame(); - gStartNewGame = 1; - gGameMenuMgr.Deactivate(); - return OSDCMD_OK; - } - levelSetupOptions(volume, level); - StartLevel(&gGameOptions); - viewResizeView(gViewSize); - gGameMenuMgr.Deactivate(); - - return OSDCMD_OK; -} - static int osdcmd_map(osdcmdptr_t parm) { char filename[BMAX_PATH]; @@ -118,13 +71,11 @@ static int osdcmd_map(osdcmdptr_t parm) gPacketStartGame.levelId = gGameOptions.nLevel; netBroadcastNewGame(); gStartNewGame = 1; - gGameMenuMgr.Deactivate(); return OSDCMD_OK; } levelSetupOptions(gGameOptions.nEpisode, gGameOptions.nLevel); StartLevel(&gGameOptions); viewResizeView(gViewSize); - gGameMenuMgr.Deactivate(); return OSDCMD_OK; } @@ -153,43 +104,6 @@ static int osdcmd_demo(osdcmdptr_t parm) return OSDCMD_OK; } -static int osdcmd_music(osdcmdptr_t parm) -{ - char buffer[128]; - if (parm->numparms == 1) - { - int32_t sel = levelGetMusicIdx(parm->parms[0]); - - if (sel == -1) - return OSDCMD_SHOWHELP; - - if (sel == -2) - { - OSD_Printf("%s is not a valid episode/level number pair\n", parm->parms[0]); - return OSDCMD_OK; - } - - int nEpisode = sel/kMaxLevels; - int nLevel = sel%kMaxLevels; - - if (!levelTryPlayMusic(nEpisode, nLevel)) - { - if (mus_redbook) - snprintf(buffer, sizeof(buffer), "Playing %i track", gEpisodeInfo[nEpisode].at28[nLevel].ate0); - else - snprintf(buffer, sizeof(buffer), "Playing %s", gEpisodeInfo[nEpisode].at28[nLevel].atd0); - viewSetMessage(buffer); - } - else - { - OSD_Printf("No music defined for %s\n", parm->parms[0]); - } - - return OSDCMD_OK; - } - - return OSDCMD_SHOWHELP; -} static int osdcmd_vidmode(osdcmdptr_t parm) { @@ -367,112 +281,22 @@ static int osdcmd_restartsound(osdcmdptr_t UNUSED(parm)) sndInit(); sfxInit(); - if (MusicEnabled() && (gGameStarted || gDemo.at1)) - sndPlaySong(nullptr, "*", true); - return OSDCMD_OK; } void onvideomodechange(int32_t newmode) { UNREFERENCED_PARAMETER(newmode); -#if 0 - uint8_t palid; - // XXX? - if (!newmode || g_player[screenpeek].ps->palette < BASEPALCOUNT) - palid = g_player[screenpeek].ps->palette; - else - palid = BASEPAL; - -#ifdef POLYMER - if (videoGetRenderMode() == REND_POLYMER) - { - int32_t i = 0; - - while (i < MAXSPRITES) - { - if (actor[i].lightptr) - { - polymer_deletelight(actor[i].lightId); - actor[i].lightptr = NULL; - actor[i].lightId = -1; - } - i++; - } - } -#endif - - videoSetPalette(0, palid, 0); - g_restorePalette = -1; -#endif if (newmode) scrResetPalette(); UpdateDacs(gLastPal, false); } -static int osdcmd_quicksave(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - if (!gGameStarted || gDemo.at1 || gGameMenuMgr.m_bActive) - OSD_Printf("quicksave: not in a game.\n"); - else gDoQuickSave = 1; - return OSDCMD_OK; -} -static int osdcmd_quickload(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - if (!gGameStarted || gDemo.at1 || gGameMenuMgr.m_bActive) - OSD_Printf("quickload: not in a game.\n"); - else gDoQuickSave = 2; - return OSDCMD_OK; -} - -static int osdcmd_screenshot(osdcmdptr_t parm) -{ - videoCaptureScreen(); - - return OSDCMD_OK; -} - -#if 0 -static int osdcmd_savestate(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_PARAMETER(parm); - G_SaveMapState(); - return OSDCMD_OK; -} - -static int osdcmd_restorestate(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_PARAMETER(parm); - G_RestoreMapState(); - return OSDCMD_OK; -} -#endif - -#if 0 -#ifdef DEBUGGINGAIDS -static int osdcmd_inittimer(osdcmdptr_t parm) -{ - if (parm->numparms != 1) - { - OSD_Printf("%dHz timer\n",g_timerTicsPerSecond); - return OSDCMD_SHOWHELP; - } - - G_InitTimer(Batol(parm->parms[0])); - - OSD_Printf("%s\n",parm->raw); - return OSDCMD_OK; -} -#endif -#endif int32_t registerosdcommands(void) { - OSD_RegisterFunction("changelevel","changelevel : warps to the given level", osdcmd_changelevel); OSD_RegisterFunction("map","map : loads the given user map", osdcmd_map); OSD_RegisterFunction("demo","demo : starts the given demo", osdcmd_demo); OSD_RegisterFunction("crosshaircolor","crosshaircolor: changes the crosshair color", osdcmd_crosshaircolor); @@ -480,12 +304,8 @@ int32_t registerosdcommands(void) OSD_RegisterFunction("give","give : gives requested item", osdcmd_give); OSD_RegisterFunction("god","god: toggles god mode", osdcmd_god); - OSD_RegisterFunction("music","music EL: change music", osdcmd_music); OSD_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip); - OSD_RegisterFunction("quicksave","quicksave: performs a quick save", osdcmd_quicksave); - OSD_RegisterFunction("quickload","quickload: performs a quick load", osdcmd_quickload); OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound); - OSD_RegisterFunction("screenshot","screenshot [format]: takes a screenshot.", osdcmd_screenshot); OSD_RegisterFunction("vidmode","vidmode : change the video mode",osdcmd_vidmode); diff --git a/source/blood/src/player.cpp b/source/blood/src/player.cpp index 8512ee832..6853e0095 100644 --- a/source/blood/src/player.cpp +++ b/source/blood/src/player.cpp @@ -53,6 +53,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "weapon.h" #include "common_game.h" #include "messages.h" +#include "gstrings.h" BEGIN_BLD_NS @@ -1468,7 +1469,7 @@ char PickupWeapon(PLAYER *pPlayer, spritetype *pWeapon) { void PickUp(PLAYER *pPlayer, spritetype *pSprite) { - char buffer[80]; + const char *msg = nullptr; int nType = pSprite->type; char pickedUp = 0; int customMsg = -1; @@ -1481,15 +1482,15 @@ void PickUp(PLAYER *pPlayer, spritetype *pSprite) if (nType >= kItemBase && nType <= kItemMax) { pickedUp = PickupItem(pPlayer, pSprite); - if (pickedUp && customMsg == -1) sprintf(buffer, "Picked up %s", gItemText[nType - kItemBase]); + if (pickedUp && customMsg == -1) msg = GStrings(FStringf("TXTB_ITEM%02d", int(nType - kItemBase +1))); } else if (nType >= kItemAmmoBase && nType < kItemAmmoMax) { pickedUp = PickupAmmo(pPlayer, pSprite); - if (pickedUp && customMsg == -1) sprintf(buffer, "Picked up %s", gAmmoText[nType - kItemAmmoBase]); + if (pickedUp && customMsg == -1) msg = GStrings(FStringf("TXTB_AMMO%02d", int(nType - kItemAmmoBase +1))); } else if (nType >= kItemWeaponBase && nType < kItemWeaponMax) { pickedUp = PickupWeapon(pPlayer, pSprite); - if (pickedUp && customMsg == -1) sprintf(buffer, "Picked up %s", gWeaponText[nType - kItemWeaponBase]); + if (pickedUp && customMsg == -1) msg = GStrings(FStringf("TXTB_WPN%02d", int(nType - kItemWeaponBase +1))); } if (!pickedUp) return; @@ -1505,7 +1506,7 @@ void PickUp(PLAYER *pPlayer, spritetype *pSprite) pPlayer->pickupEffect = 30; if (pPlayer == gMe) { if (customMsg > 0) trTextOver(customMsg - 1); - else viewSetMessage(buffer, 0, MESSAGE_PRIORITY_PICKUP); + else if (msg) viewSetMessage(msg, 0, MESSAGE_PRIORITY_PICKUP); } } @@ -1798,14 +1799,14 @@ void ProcessInput(PLAYER *pPlayer) int key = pXSector->Key; if (pXSector->locked && pPlayer == gMe) { - viewSetMessage("It's locked"); + viewSetMessage(GStrings("TXTB_LOCKED")); sndStartSample(3062, 255, 2, 0); } if (!key || pPlayer->hasKey[key]) trTriggerSector(a2, pXSector, kCmdSpritePush, nSprite); else if (pPlayer == gMe) { - viewSetMessage("That requires a key."); + viewSetMessage(GStrings("TXTB_KEY")); sndStartSample(3063, 255, 2, 0); } } @@ -1816,14 +1817,14 @@ void ProcessInput(PLAYER *pPlayer) int key = pXWall->key; if (pXWall->locked && pPlayer == gMe) { - viewSetMessage("It's locked"); + viewSetMessage(GStrings("TXTB_LOCKED")); sndStartSample(3062, 255, 2, 0); } if (!key || pPlayer->hasKey[key]) trTriggerWall(a2, pXWall, kCmdWallPush, pPlayer->nSprite); else if (pPlayer == gMe) { - viewSetMessage("That requires a key."); + viewSetMessage(GStrings("TXTB_KEY")); sndStartSample(3063, 255, 2, 0); } break; @@ -1838,7 +1839,7 @@ void ProcessInput(PLAYER *pPlayer) trTriggerSprite(a2, pXSprite, kCmdSpritePush, pPlayer->nSprite); else if (pPlayer == gMe) { - viewSetMessage("That requires a key."); + viewSetMessage(GStrings("TXTB_KEY")); sndStartSample(3063, 255, 2, 0); } break; @@ -2157,7 +2158,7 @@ void playerFrag(PLAYER *pKiller, PLAYER *pVictim) int nSound = gSuicide[nMessage].at4; if (pVictim == gMe && gMe->handTime <= 0) { - sprintf(buffer, "You killed yourself!"); + sprintf(buffer, GStrings("TXTB_KILLSELF")); if (gGameOptions.nGameType > 0 && nSound >= 0) sndStartSample(nSound, 255, 2, 0); } @@ -2487,7 +2488,7 @@ void PlayerSurvive(int, int nXSprite) { PLAYER *pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; if (pPlayer == gMe) - viewSetMessage("I LIVE...AGAIN!!"); + viewSetMessage(GStrings("TXT_LIVEAGAIM")); else { sprintf(buffer, "%s lives again!", gProfile[pPlayer->nPlayer].name); diff --git a/source/blood/src/screentext.cpp b/source/blood/src/screentext.cpp index 8267aea4d..c0cc18735 100644 --- a/source/blood/src/screentext.cpp +++ b/source/blood/src/screentext.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "blood.h" #include "common_game.h" #include "screentext.h" -#include "menus.h" BEGIN_BLD_NS @@ -832,282 +831,6 @@ vec2_t G_ScreenTextShadow(int32_t sx, int32_t sy, return size; } -#if 0 -void G_PrintGameText(int32_t tile, int32_t x, int32_t y, const char *t, - int32_t s, int32_t p, int32_t o, - int32_t x1, int32_t y1, int32_t x2, int32_t y2, - int32_t z, int32_t a) -{ - int32_t f = TEXT_GAMETEXTNUMHACK; - if (t == NULL) - return; - - if (!(o & ROTATESPRITE_FULL16)) - { - x <<= 16; - y <<= 16; - } - - if (x == (160<<16)) - f |= TEXT_XCENTER; - - G_ScreenText(tile, x, y, z, 0, 0, t, s, p, 2|o|ROTATESPRITE_FULL16, a, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags|f, x1, y1, x2, y2); -} - -vec2_t gametext_(int32_t x, int32_t y, const char *t, int32_t s, int32_t p, int32_t o, int32_t a, int32_t f) -{ - return G_ScreenText(MF_Bluefont.tilenum, x, y, MF_Bluefont.zoom, 0, 0, t, s, p, o|2|8|16|ROTATESPRITE_FULL16, a, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags|f, 0, 0, xdim-1, ydim-1); -} -void gametext_simple(int32_t x, int32_t y, const char *t) -{ - G_ScreenText(MF_Bluefont.tilenum, x, y, MF_Bluefont.zoom, 0, 0, t, 0, MF_Bluefont.pal, 2|8|16|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags, 0, 0, xdim-1, ydim-1); -} -vec2_t mpgametext(int32_t x, int32_t y, const char *t, int32_t s, int32_t o, int32_t a, int32_t f) -{ - return G_ScreenText(MF_Bluefont.tilenum, x, y, textsc(MF_Bluefont.zoom), 0, 0, t, s, MF_Bluefont.pal, o|2|8|16|ROTATESPRITE_FULL16, a, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags|f, 0, 0, xdim-1, ydim-1); -} -vec2_t mpgametextsize(const char *t, int32_t f) -{ - return G_ScreenTextSize(MF_Bluefont.tilenum, 0, 0, textsc(MF_Bluefont.zoom), 0, t, 2|8|16|ROTATESPRITE_FULL16, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags|f, 0, 0, xdim-1, ydim-1); -} - -// minitext_yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords, -// (sb&ROTATESPRITE_MAX) only. -int32_t minitext_yofs = 0; -int32_t minitext_lowercase = 0; -int32_t minitext_(int32_t x, int32_t y, const char *t, int32_t s, int32_t p, int32_t sb) -{ - vec2_t dim; - int32_t z = MF_Minifont.zoom; - - if (t == NULL) - { - OSD_Printf("minitext: NULL text!\n"); - return 0; - } - - if (!(sb & ROTATESPRITE_FULL16)) - { - x<<=16; - y<<=16; - } - - if (sb & ROTATESPRITE_MAX) - { - x = sbarx16(x); - y = minitext_yofs+sbary16(y); - z = sbarsc(z); - } - - sb &= (ROTATESPRITE_MAX-1)|RS_CENTERORIGIN; - - dim = G_ScreenText(MF_Minifont.tilenum, x, y, z, 0, 0, t, s, p, sb|ROTATESPRITE_FULL16, 0, MF_Minifont.emptychar.x, MF_Minifont.emptychar.y, MF_Minifont.between.x, MF_Minifont.between.y, MF_Minifont.textflags, 0, 0, xdim-1, ydim-1); - - x += dim.x; - - if (!(sb & ROTATESPRITE_FULL16)) - x >>= 16; - - return x; -} - -void menutext_(int32_t x, int32_t y, int32_t s, char const *t, int32_t o, int32_t f) -{ - G_ScreenText(MF_Redfont.tilenum, x, y - (12<<16), MF_Redfont.zoom, 0, 0, t, s, MF_Redfont.pal, o|ROTATESPRITE_FULL16, 0, MF_Redfont.emptychar.x, MF_Redfont.emptychar.y, MF_Redfont.between.x, MF_Redfont.between.y, f|MF_Redfont.textflags|TEXT_LITERALESCAPE, 0, 0, xdim-1, ydim-1); -} - -void captionmenutext(int32_t x, int32_t y, char const *t) -{ - G_ScreenText(MF_Redfont.tilenum, x, y - (12<<16), MF_Redfont.zoom, 0, 0, t, 0, ud.menutitle_pal, 2|8|16|ROTATESPRITE_FULL16, 0, MF_Redfont.emptychar.x, MF_Redfont.emptychar.y, MF_Redfont.between.x, MF_Redfont.between.y, MF_Redfont.textflags|TEXT_LITERALESCAPE|TEXT_XCENTER|TEXT_YCENTER, 0, 0, xdim-1, ydim-1); -} - - -int32_t user_quote_time[MAXUSERQUOTES]; -static char user_quote[MAXUSERQUOTES][178]; - -void G_AddUserQuote(const char *daquote) -{ - int32_t i; - - for (i=MAXUSERQUOTES-1; i>0; i--) - { - Bstrcpy(user_quote[i], user_quote[i-1]); - user_quote_time[i] = user_quote_time[i-1]; - } - Bstrcpy(user_quote[0], daquote); - OSD_Printf("%s\n", daquote); - - user_quote_time[0] = hud_messagetime; - pub = NUMPAGES; -} - -int32_t textsc(int32_t sc) -{ - return scale(sc, hud_textscale, 400); -} - - -#define FTAOPAQUETIME 30 - -// alpha increments of 8 --> 256 / 8 = 32 --> round up to power of 2 --> 32 --> divide by 2 --> 16 alphatabs required -static inline int32_t textsh(uint32_t t) -{ - return (hud_glowingquotes && ((videoGetRenderMode() == REND_CLASSIC && numalphatabs < 15) || t >= FTAOPAQUETIME)) - ? sintable[(t << 7) & 2047] >> 11 - : (sintable[(FTAOPAQUETIME << 7) & 2047] >> 11); -} - -// orientation flags depending on time that a quote has still to be displayed -static inline int32_t texto(int32_t t) -{ - if (videoGetRenderMode() != REND_CLASSIC || numalphatabs >= 15 || t > 4) - return 0; - - if (t > 2) - return 1; - - return 1|32; -} - -static inline int32_t texta(int32_t t) -{ - if (videoGetRenderMode() == REND_CLASSIC && numalphatabs < 15) - return 0; - - return 255 - clamp(t<<3, 0, 255); -} - -static FORCE_INLINE int32_t text_ypos(void) -{ - if (hud_position == 1 && ud.screen_size == 4 && ud.althud == 1) - return 32<<16; - -#ifdef GEKKO - return 16<<16; -#elif defined EDUKE32_TOUCH_DEVICES - return 24<<16; -#else - return 1<<16; -#endif -} - -// this handles both multiplayer and item pickup message type text -// both are passed on to gametext -void G_PrintGameQuotes(int32_t snum) -{ - auto const ps = g_player[snum].ps; - const int32_t reserved_quote = (ps->ftq >= QUOTE_RESERVED && ps->ftq <= QUOTE_RESERVED3); - // NOTE: QUOTE_RESERVED4 is not included. - - int32_t const ybase = (fragbarheight()<<16) + text_ypos(); - int32_t height = 0; - int32_t k = ps->fta; - - - // primary quote - - do - { - if (k <= 1) - break; - - if (EDUKE32_PREDICT_FALSE(apStrings[ps->ftq] == NULL)) - { - OSD_Printf(OSD_ERROR "%s %d null quote %d\n", "screentext:", __LINE__, ps->ftq); - break; - } - - int32_t y = ybase; - if (reserved_quote) - { -#ifdef SPLITSCREEN_MOD_HACKS - if (!g_fakeMultiMode) - y = 140<<16; - else - y = 70<<16; -#else - y = 140<<16; -#endif - } - - int32_t pal = 0; - int32_t x = 160<<16; - -#ifdef SPLITSCREEN_MOD_HACKS - if (g_fakeMultiMode) - { - pal = g_player[snum].pcolor; - const int32_t sidebyside = ud.screen_size != 0; - - if (sidebyside) - x = snum == 1 ? 240<<16 : 80<<16; - else if (snum == 1) - y += 100<<16; - } -#endif - - height = gametext_(x, y, apStrings[ps->ftq], textsh(k), pal, texto(k), texta(k), TEXT_XCENTER).y + (1<<16); - } - while (0); - - - // userquotes - - int32_t y = ybase; - - if (k > 1 && !reserved_quote) - y += k <= 8 ? (height * (k-1))>>3 : height; - - for (int i = 0; i < MAXUSERQUOTES; i++) - { - k = user_quote_time[i]; - - if (k <= 0) - continue; - - // int32_t const sh = hud_glowingquotes ? sintable[((totalclock+(i<<2))<<5)&2047]>>11 : 0; - - height = mpgametext(mpgametext_x, y, user_quote[i], textsh(k), texto(k), texta(k), TEXT_LINEWRAP).y + textsc(1<<16); - y += k <= 4 ? (height * (k-1))>>2 : height; - } -} - -void P_DoQuote(int32_t q, DukePlayer_t *p) -{ - int32_t cq = 0; - - if (hud_messages == 0 || q < 0 || !(p->gm & MODE_GAME)) - return; - - if (q & MAXQUOTES) - { - cq = 1; - q &= ~MAXQUOTES; - } - - if (EDUKE32_PREDICT_FALSE(apStrings[q] == NULL)) - { - OSD_Printf(OSD_ERROR "%s %d null quote %d\n", "screentext:", __LINE__, q); - return; - } - - if (p->fta > 0 && q != QUOTE_RESERVED && q != QUOTE_RESERVED2) - if (p->ftq == QUOTE_RESERVED || p->ftq == QUOTE_RESERVED2) return; - - p->fta = 100; - - if (p->ftq != q) - { - if (p == g_player[screenpeek].ps && apStrings[q][0] != '\0') - OSD_Printf(cq ? OSDTEXT_DEFAULT "%s\n" : "%s\n", apStrings[q]); - - p->ftq = q; - } - - pub = NUMPAGES; - pus = NUMPAGES; -} -#endif END_BLD_NS diff --git a/source/blood/src/screentext.h b/source/blood/src/screentext.h index 6824a3eb8..693b64976 100644 --- a/source/blood/src/screentext.h +++ b/source/blood/src/screentext.h @@ -22,8 +22,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #pragma once -#include "menus.h" - BEGIN_BLD_NS #define USERQUOTE_LEFTOFFSET 5 diff --git a/source/blood/src/sound.cpp b/source/blood/src/sound.cpp index 5dd1b1d74..c844d5e3a 100644 --- a/source/blood/src/sound.cpp +++ b/source/blood/src/sound.cpp @@ -75,178 +75,6 @@ SAMPLE2D * FindChannel(void) return NULL; } -#if 0 -DICTNODE *hSong; -char *pSongPtr; -int nSongSize; -bool bWaveMusic; -int nWaveMusicHandle; - -int sndPlaySong(const char *, const char* songName, bool bLoop) -{ - if (!MusicEnabled()) - return 0; - if (!songName || strlen(songName) == 0) - return 1; - - auto fp = S_OpenAudio(songName, 0, 1); - if (!fp.isOpen()) - { - hSong = gSoundRes.Lookup(songName, "MID"); - if (!hSong) - { - OSD_Printf(OSD_ERROR "sndPlaySong(): error: can't open \"%s\" for playback!\n", songName); - return 2; - } - int nNewSongSize = hSong->Size(); - char *pNewSongPtr = (char *)Xaligned_alloc(16, nNewSongSize); - memcpy(pNewSongPtr, hSong->Lock(), nNewSongSize); - hSong->Unlock(true); - MUSIC_SetVolume(mus_volume); - int32_t retval = MUSIC_PlaySong(pNewSongPtr, nNewSongSize, bLoop); - - if (retval != MUSIC_Ok) - { - ALIGNED_FREE_AND_NULL(pNewSongPtr); - return 5; - } - - if (bWaveMusic && nWaveMusicHandle >= 0) - { - FX_StopSound(nWaveMusicHandle); - nWaveMusicHandle = -1; - } - - bWaveMusic = false; - ALIGNED_FREE_AND_NULL(pSongPtr); - pSongPtr = pNewSongPtr; - nSongSize = nNewSongSize; - return 0; - } - - int32_t nSongLen = fp.Tell(); - - if (EDUKE32_PREDICT_FALSE(nSongLen < 4)) - { - OSD_Printf(OSD_ERROR "sndPlaySong(): error: empty music file \"%s\"\n", songName); - return 3; - } - - char * pNewSongPtr = (char *)Xaligned_alloc(16, nSongLen); - int nNewSongSize = fp.Read(pNewSongPtr, nSongLen); - - if (EDUKE32_PREDICT_FALSE(nNewSongSize != nSongLen)) - { - OSD_Printf(OSD_ERROR "sndPlaySong(): error: read %d bytes from \"%s\", expected %d\n", - nNewSongSize, songName, nSongLen); - ALIGNED_FREE_AND_NULL(pNewSongPtr); - return 4; - } - - if (!Bmemcmp(pNewSongPtr, "MThd", 4)) - { - int32_t retval = MUSIC_PlaySong(pNewSongPtr, nNewSongSize, bLoop); - - if (retval != MUSIC_Ok) - { - ALIGNED_FREE_AND_NULL(pNewSongPtr); - return 5; - } - - if (bWaveMusic && nWaveMusicHandle >= 0) - { - FX_StopSound(nWaveMusicHandle); - nWaveMusicHandle = -1; - } - - bWaveMusic = false; - ALIGNED_FREE_AND_NULL(pSongPtr); - pSongPtr = pNewSongPtr; - nSongSize = nNewSongSize; - } - else - { - int nNewWaveMusicHandle = FX_Play(pNewSongPtr, bLoop ? nNewSongSize : -1, 0, 0, 0, mus_volume, mus_volume, mus_volume, - FX_MUSIC_PRIORITY, 1.f, (intptr_t)&nWaveMusicHandle); - - if (nNewWaveMusicHandle <= FX_Ok) - { - ALIGNED_FREE_AND_NULL(pNewSongPtr); - return 5; - } - - if (bWaveMusic && nWaveMusicHandle >= 0) - FX_StopSound(nWaveMusicHandle); - - MUSIC_StopSong(); - - nWaveMusicHandle = nNewWaveMusicHandle; - bWaveMusic = true; - ALIGNED_FREE_AND_NULL(pSongPtr); - pSongPtr = pNewSongPtr; - nSongSize = nNewSongSize; - } - - return 0; -} - -bool sndIsSongPlaying(void) -{ - //return MUSIC_SongPlaying(); - return false; -} - -void sndFadeSong(int nTime) -{ - UNREFERENCED_PARAMETER(nTime); - - if (bWaveMusic && nWaveMusicHandle >= 0) - { - FX_StopSound(nWaveMusicHandle); - nWaveMusicHandle = -1; - bWaveMusic = false; - } - // MUSIC_SetVolume(0); - MUSIC_StopSong(); -} - -void sndStopSong(void) -{ - if (bWaveMusic && nWaveMusicHandle >= 0) - { - FX_StopSound(nWaveMusicHandle); - nWaveMusicHandle = -1; - bWaveMusic = false; - } - - MUSIC_StopSong(); - - ALIGNED_FREE_AND_NULL(pSongPtr); - nSongSize = 0; -} -#else -int sndPlaySong(const char *mapname, const char* songName, bool bLoop) -{ - return Mus_Play(mapname, songName, bLoop); -} - -bool sndIsSongPlaying(void) -{ - // Not used - return false; -} - -void sndFadeSong(int nTime) -{ - // not implemented -} - -void sndStopSong(void) -{ - Mus_Stop(); -} -#endif - void sndSetFXVolume(int nVolume) { snd_fxvolume = nVolume; @@ -367,7 +195,7 @@ void sndStartWavDisk(const char *pzFile, int nVolume, int nChannel) pChannel = &Channel[nChannel]; if (pChannel->at0 > 0) sndKillSound(pChannel); - auto hFile = kopenFileReader(pzFile, 0); + auto hFile = fileSystem.OpenFileReader(pzFile, 0); if (!hFile.isOpen()) return; int nLength = hFile.GetLength(); @@ -450,34 +278,6 @@ void DeinitSoundDevice(void) ThrowError(FX_ErrorString(nStatus)); } -#if 0 -void InitMusicDevice(void) -{ - int nStatus; - if ((nStatus = MUSIC_Init(MusicDevice)) == MUSIC_Ok) - { - if (MusicDevice == ASS_AutoDetect) - MusicDevice = MIDI_GetDevice(); - } - else if ((nStatus = MUSIC_Init(ASS_AutoDetect)) == MUSIC_Ok) - { - initprintf("InitMusicDevice: %s\n", MUSIC_ErrorString(nStatus)); - return; - } - DICTNODE *hTmb = gSoundRes.Lookup("GMTIMBRE", "TMB"); - if (hTmb) - AL_RegisterTimbreBank((unsigned char*)gSoundRes.Load(hTmb)); - MUSIC_SetVolume(mus_volume); -} - -void DeinitMusicDevice(void) -{ - FX_StopAllSounds(); - int nStatus = MUSIC_Shutdown(); - if (nStatus != 0) - ThrowError(MUSIC_ErrorString(nStatus)); -} -#endif bool sndActive = false; @@ -486,7 +286,7 @@ void sndTerm(void) if (!sndActive) return; sndActive = false; - sndStopSong(); + Mus_Stop(); DeinitSoundDevice(); //DeinitMusicDevice(); } diff --git a/source/blood/src/sound.h b/source/blood/src/sound.h index 44b101e29..ccc31501e 100644 --- a/source/blood/src/sound.h +++ b/source/blood/src/sound.h @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #pragma once #include "resource.h" +#include "z_music.h" BEGIN_BLD_NS @@ -44,12 +45,7 @@ struct SFX }; int sndGetRate(int format); -int sndPlaySong(const char *mapname, const char *songName, bool bLoop); -bool sndIsSongPlaying(void); -void sndFadeSong(int nTime); -void sndSetMusicVolume(int nVolume); void sndSetFXVolume(int nVolume); -void sndStopSong(void); void sndStartSample(const char *pzSound, int nVolume, int nChannel = -1); void sndStartSample(unsigned int nSound, int nVolume, int nChannel = -1, bool bLoop = false); void sndStartWavID(unsigned int nSound, int nVolume, int nChannel = -1); diff --git a/source/blood/src/tile.cpp b/source/blood/src/tile.cpp index c700fbb76..cfb857af2 100644 --- a/source/blood/src/tile.cpp +++ b/source/blood/src/tile.cpp @@ -86,12 +86,12 @@ int tileInit(char a1, const char *a2) for (int i = 0; i < kMaxTiles; i++) voxelIndex[i] = 0; - auto hFile = kopenFileReader("SURFACE.DAT", 0); + auto hFile = fileSystem.OpenFileReader("SURFACE.DAT", 0); if (hFile.isOpen()) { hFile.Read(surfType, sizeof(surfType)); } - hFile = kopenFileReader("VOXEL.DAT", 0); + hFile = fileSystem.OpenFileReader("VOXEL.DAT", 0); if (hFile.isOpen()) { hFile.Read(voxelIndex, sizeof(voxelIndex)); @@ -100,7 +100,7 @@ int tileInit(char a1, const char *a2) voxelIndex[i] = B_LITTLE16(voxelIndex[i]); #endif } - hFile = kopenFileReader("SHADE.DAT", 0); + hFile = fileSystem.OpenFileReader("SHADE.DAT", 0); if (hFile.isOpen()) { hFile.Read(tileShade, sizeof(tileShade)); diff --git a/source/blood/src/triggers.cpp b/source/blood/src/triggers.cpp index f1c310bff..6814d62c5 100644 --- a/source/blood/src/triggers.cpp +++ b/source/blood/src/triggers.cpp @@ -4769,7 +4769,7 @@ void trInit(void) void trTextOver(int nId) { - char *pzMessage = levelGetMessage(nId); + const char *pzMessage = levelGetMessage(nId); if (pzMessage) viewSetMessage(pzMessage, VanillaMode() ? 0 : 8, MESSAGE_PRIORITY_INI); // 8: gold } diff --git a/source/blood/src/view.cpp b/source/blood/src/view.cpp index ef6829df5..6b0575aab 100644 --- a/source/blood/src/view.cpp +++ b/source/blood/src/view.cpp @@ -47,7 +47,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "loadsave.h" #include "map2d.h" #include "messages.h" -#include "menu.h" +#include "gamemenu.h" #include "mirrors.h" #include "network.h" #include "player.h" @@ -61,6 +61,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "warp.h" #include "weapon.h" #include "zstring.h" +#include "menu/menu.h" +#include "gstrings.h" CVARD(Bool, hud_powerupduration, true, CVAR_ARCHIVE|CVAR_FRONTEND_BLOOD, "enable/disable displaying the remaining seconds for power-ups") @@ -1003,39 +1005,6 @@ void viewDrawText(int nFont, const char *pString, int x, int y, int nShade, int if (shadow) G_ScreenText(pFont->tile, x + 1, y + 1, 65536, 0, 0, pString, 127, nPalette, 2|8|16|nStat, alpha, 0, 0, pFont->space, 0, nFlags, 0, 0, xdim-1, ydim-1); G_ScreenText(pFont->tile, x, y, 65536, 0, 0, pString, nShade, nPalette, 2|8|16|nStat, alpha, 0, 0, pFont->space, 0, nFlags, 0, 0, xdim-1, ydim-1); - //if (nFont < 0 || nFont >= 5 || !pString) return; - //FONT *pFont = &gFont[nFont]; - // - //if (position) - //{ - // const char *s = pString; - // int width = -pFont->space; - // while (*s) - // { - // int nTile = ((*s-' ')&127)+pFont->tile; - // if (tilesiz[nTile].x && tilesiz[nTile].y) - // width += tilesiz[nTile].x+pFont->space; - // s++; - // } - // if (position == 1) - // width >>= 1; - // x -= width; - //} - //const char *s = pString; - //while (*s) - //{ - // int nTile = ((*s-' ')&127) + pFont->tile; - // if (tilesiz[nTile].x && tilesiz[nTile].y) - // { - // if (shadow) - // { - // rotatesprite_fs_alpha((x+1)<<16, (y+1)<<16, 65536, 0, nTile, 127, nPalette, 26|nStat, alpha); - // } - // rotatesprite_fs_alpha(x<<16, y<<16, 65536, 0, nTile, nShade, nPalette, 26|nStat, alpha); - // x += tilesiz[nTile].x+pFont->space; - // } - // s++; - //} } void viewTileSprite(int nTile, int nShade, int nPalette, int x1, int y1, int x2, int y2) @@ -1196,6 +1165,11 @@ void viewDrawStats(PLAYER *pPlayer, int x, int y) viewDrawText(3, buffer, x, y, 20, 0, 0, true, 256); } +GameStats GameInterface::getStats() +{ + return { gKillMgr.at4, gKillMgr.at0, gSecretMgr.at8, gSecretMgr.at0, gLevelTime / kTicsPerSec, gPlayer[myconnectindex].fragCount }; +} + #define kSBarNumberHealth 9220 #define kSBarNumberAmmo 9230 #define kSBarNumberInv 9240 @@ -1270,7 +1244,7 @@ void viewDrawPowerUps(PLAYER* pPlayer) void viewDrawMapTitle(void) { - if (!hud_showmapname || gGameMenuMgr.m_bActive) + if (!hud_showmapname || M_Active()) return; int const fadeStartTic = int((videoGetRenderMode() == REND_CLASSIC ? 1.25f : 1.f)*kTicsPerSec); @@ -1428,7 +1402,7 @@ void viewDrawCtfHudVanilla(ClockTicks arg) int x = 1, y = 1; if (dword_21EFD0[0] == 0 || ((int)totalclock & 8)) { - viewDrawText(0, "BLUE", x, y, -128, 10, 0, 0, 256); + viewDrawText(0, GStrings("TXT_COLOR_BLUE"), x, y, -128, 10, 0, 0, 256); dword_21EFD0[0] = dword_21EFD0[0] - arg; if (dword_21EFD0[0] < 0) dword_21EFD0[0] = 0; @@ -1438,7 +1412,7 @@ void viewDrawCtfHudVanilla(ClockTicks arg) x = 319; if (dword_21EFD0[1] == 0 || ((int)totalclock & 8)) { - viewDrawText(0, "RED", x, y, -128, 7, 2, 0, 512); + viewDrawText(0, GStrings("TXT_COLOR_RED"), x, y, -128, 7, 2, 0, 512); dword_21EFD0[1] = dword_21EFD0[1] - arg; if (dword_21EFD0[1] < 0) dword_21EFD0[1] = 0; @@ -2791,16 +2765,23 @@ void viewSetSystemMessage(const char* pMessage, ...) { char buffer[1024]; va_list args; va_start(args, pMessage); vsprintf(buffer, pMessage, args); - OSD_Printf("%s\n", buffer); // print it also in console + Printf(PRINT_HIGH | PRINT_NOTIFY, "%s\n", buffer); // print it also in console gGameMessageMgr.Add(buffer, 15, 7, MESSAGE_PRIORITY_SYSTEM); } void viewSetMessage(const char *pMessage, const int pal, const MESSAGE_PRIORITY priority) { - OSD_Printf("%s\n", pMessage); + int printlevel = priority < 0 ? PRINT_LOW : priority < MESSAGE_PRIORITY_SYSTEM ? PRINT_MEDIUM : PRINT_HIGH; + Printf(printlevel|PRINT_NOTIFY, "%s\n", pMessage); gGameMessageMgr.Add(pMessage, 15, pal, priority); } +void GameInterface::DoPrintMessage(int prio, const char*msg) +{ + viewSetMessage(msg, 0, prio == PRINT_LOW ? MESSAGE_PRIORITY_PICKUP : prio == PRINT_MEDIUM ? MESSAGE_PRIORITY_NORMAL : MESSAGE_PRIORITY_SYSTEM); +} + + void viewDisplayMessage(void) { gGameMessageMgr.Display(); @@ -3056,7 +3037,7 @@ void viewDrawScreen(void) if (delta < 0) delta = 0; lastUpdate = totalclock; - if (!gPaused && (!CGameMenuMgr::m_bActive || gGameOptions.nGameType != 0)) + if (!gPaused && (!M_Active() || gGameOptions.nGameType != 0)) { gInterpolate = ((totalclock-gNetFifoClock)+4).toScale16()/4; } @@ -3577,7 +3558,7 @@ RORHACK: viewDrawAimedPlayerName(); if (gPaused) { - viewDrawText(1, "PAUSED", 160, 10, 0, 0, 1, 0); + viewDrawText(1, GStrings("TXTB_PAUSED"), 160, 10, 0, 0, 1, 0); } else if (gView != gMe) { @@ -3631,7 +3612,7 @@ void viewLoadingScreenWide(void) void viewLoadingScreenUpdate(const char *pzText4, int nPercent) { int vc; - gMenuTextMgr.GetFontInfo(1, NULL, NULL, &vc); + viewGetFontInfo(1, NULL, NULL, &vc); if (nLoadingScreenTile == kLoadScreen) viewLoadingScreenWide(); else if (nLoadingScreenTile) @@ -3660,7 +3641,7 @@ void viewLoadingScreenUpdate(const char *pzText4, int nPercent) if (nPercent != -1) TileHGauge(2260, 86, 110, nPercent, 100, 0, 131072); - viewDrawText(3, "Please Wait", 160, 134, -128, 0, 1, 1); + viewDrawText(3, GStrings("TXTB_PLSWAIT"), 160, 134, -128, 0, 1, 1); } void viewLoadingScreen(int nTile, const char *pText, const char *pText2, const char *pText3) diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h index 2e0cb6ce2..979f2e95f 100644 --- a/source/build/include/baselayer.h +++ b/source/build/include/baselayer.h @@ -14,6 +14,7 @@ #include "inputstate.h" #include "printf.h" #include "zstring.h" +#include "vectors.h" #ifdef DEBUGGINGAIDS @@ -21,7 +22,7 @@ extern int32_t g_maskDrawMode; #endif -extern char quitevent, appactive; +extern char appactive; extern char modechange; extern char nogl; @@ -115,6 +116,7 @@ typedef struct void (*pCallback)(int32_t, int32_t); int32_t bits; int32_t numAxes; + int32_t numBalls; int32_t numButtons; int32_t numHats; int32_t isGameController; @@ -144,7 +146,7 @@ void joyScanDevices(void); void mouseInit(void); void mouseUninit(void); void mouseGrabInput(bool grab); -void mouseLockToWindow(char a); +void mouseLockToWindow(bool a); void mouseMoveToCenter(void); void joyReadButtons(int32_t *pResult); @@ -166,8 +168,43 @@ struct GameStats int kill, tkill; int secret, tsecret; int timesecnd; + int frags; }; +struct FGameStartup +{ + int Episode; + int Level; + int Skill; + int CustomLevel1; + int CustomLevel2; +}; + +struct FSavegameInfo +{ + const char *savesig; + int minsavever; + int currentsavever; +}; + +struct FSaveGameNode +{ + FString SaveTitle; + FString Filename; + bool bOldVersion = false; + bool bMissingWads = false; + bool bNoDelete = false; + bool bIsExt = false; + + bool isValid() const + { + return Filename.IsNotEmpty() && !bOldVersion && !bMissingWads; + } +}; + + +enum EMenuSounds : int; + struct GameInterface { virtual ~GameInterface() {} @@ -176,9 +213,35 @@ struct GameInterface virtual bool validate_hud(int) = 0; virtual void set_hud_layout(int size) = 0; virtual void set_hud_scale(int size) = 0; - virtual bool mouseInactiveConditional(bool condition) { return condition; } virtual FString statFPS() { return "FPS display not available"; } virtual GameStats getStats() { return {}; } + virtual void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) {} + virtual void MainMenuOpened() {} + virtual void MenuOpened() {} + virtual void MenuClosed() {} + virtual void MenuSound(EMenuSounds snd) {} + virtual bool CanSave() { return true; } + virtual void CustomMenuSelection(int menu, int item) {} + virtual void StartGame(FGameStartup& gs) {} + virtual FSavegameInfo GetSaveSig() { return { "", 0, 0}; } + virtual bool DrawSpecialScreen(const DVector2 &origin, int tilenum) { return false; } + virtual void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool withbg = true) {} + virtual void DrawMenuCaption(const DVector2& origin, const char* text) {} + virtual bool SaveGame(FSaveGameNode*) { return false; } + virtual bool LoadGame(FSaveGameNode*) { return false; } + virtual void DoPrintMessage(int prio, const char*) = 0; + void PrintMessage(int prio, const char*fmt, ...) + { + va_list ap; + va_start(ap, fmt); + FString f; + f.VFormat(fmt, ap); + DoPrintMessage(prio, f); + } + virtual void DrawPlayerSprite(const DVector2& origin, bool onteam) {} + virtual void QuitToTitle() {} + virtual void SetAmbience(bool on) {} + }; extern GameInterface* gi; diff --git a/source/build/include/build.h b/source/build/include/build.h index 1d6db2064..28f1e5db1 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -891,7 +891,7 @@ void updatesectorneighbor(int32_t const x, int32_t const y, int16_t * const sect void updatesectorneighborz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum, int32_t initialMaxDistance = INITIALUPDATESECTORDIST, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(4))); int findwallbetweensectors(int sect1, int sect2); -static FORCE_INLINE bool sectoradjacent(int sect1, int sect2) { return findwallbetweensectors(sect1, sect2) != -1; } +static FORCE_INLINE int sectoradjacent(int sect1, int sect2) { return findwallbetweensectors(sect1, sect2) != -1; } int32_t getsectordist(vec2_t const in, int const sectnum, vec2_t * const out = nullptr); extern const int16_t *chsecptr_onextwall; int32_t checksectorpointer(int16_t i, int16_t sectnum); @@ -1147,7 +1147,7 @@ static FORCE_INLINE int32_t md_tilehasmodel(int32_t const tilenume, int32_t cons } #endif // defined USE_OPENGL -static FORCE_INLINE bool tilehasmodelorvoxel(int const tilenume, int pal) +static FORCE_INLINE int tilehasmodelorvoxel(int const tilenume, int pal) { UNREFERENCED_PARAMETER(pal); return @@ -1189,7 +1189,7 @@ extern const int32_t engine_v8; int32_t Mulscale(int32_t a, int32_t b, int32_t sh); #endif -static FORCE_INLINE CONSTEXPR bool inside_p(int32_t const x, int32_t const y, int const sectnum) { return (sectnum >= 0 && inside(x, y, sectnum) == 1); } +static FORCE_INLINE CONSTEXPR int inside_p(int32_t const x, int32_t const y, int const sectnum) { return (sectnum >= 0 && inside(x, y, sectnum) == 1); } #define SET_AND_RETURN(Lval, Rval) \ do \ diff --git a/source/build/include/cache1d.h b/source/build/include/cache1d.h index 0468fe660..4e6983879 100644 --- a/source/build/include/cache1d.h +++ b/source/build/include/cache1d.h @@ -9,58 +9,7 @@ #ifndef cache1d_h_ #define cache1d_h_ -#include "compat.h" -#include "files.h" - void cacheAllocateBlock(intptr_t *newhandle, int32_t newbytes, uint8_t *newlockptr); -extern int32_t pathsearchmode; // 0 = gamefs mode (default), 1 = localfs mode (editor's mode) - -#include "filesystem/filesystem.h" - -// Wrappers for the handle based API to get rid of the direct calls without any actual changes to the implementation. -// These are now getting redirected to the file system so that the implementation here can be gutted without making changes to the calling code. -inline FileReader kopenFileReader(const char* name, int where) -{ - auto lump = fileSystem.FindFile(name); - if (lump < 0) return FileReader(); - else return fileSystem.OpenFileReader(lump); -} - -// This is only here to mark a file as not being part of the game assets (e.g. savegames) -// These should be handled differently (e.g read from a userdata directory or similar things.) -inline FileReader fopenFileReader(const char* name, int where) -{ - FileReader fr; - fr.OpenFile(name); - return fr; -} - -inline bool testkopen(const char* name, int where) -{ - // todo: if backed by a single file, we must actually open it to make sure. - return fileSystem.FindFile(name) >= 0; -} - -inline TArray kloadfile(const char* name, int where) -{ - auto lump = fileSystem.FindFile(name); - if (lump < 0) return TArray(); - return fileSystem.GetFileData(lump); -} - -inline int32_t kfilesize(const char* name, int where) -{ - auto lump = fileSystem.FindFile(name); - if (lump < 0) return -1; - return fileSystem.FileLength(lump); -} - -// checks from path and in ZIPs, returns 1 if NOT found -inline int32_t check_file_exist(const char* fn) -{ - return fileSystem.FindFile(fn) >= 0; -} - #endif // cache1d_h_ diff --git a/source/build/include/colmatch.h b/source/build/include/colmatch.h index 90c36e0ba..751ba1a68 100644 --- a/source/build/include/colmatch.h +++ b/source/build/include/colmatch.h @@ -13,7 +13,3 @@ static FORCE_INLINE int32_t paletteGetClosestColor(int32_t r, int32_t g, int32_t { return getclosestcol_lim(r, g, b, 255); } -static FORCE_INLINE int32_t getclosestcol_nocache(int32_t r, int32_t g, int32_t b) -{ - return getclosestcol_nocache_lim(r, g, b, 255); -} diff --git a/source/build/include/compat.h b/source/build/include/compat.h index 2bcbbf5a3..e0da70d05 100644 --- a/source/build/include/compat.h +++ b/source/build/include/compat.h @@ -568,7 +568,10 @@ typedef FILE BFILE; // parsing the decimal representation of 0xffffffff, // 4294967295 -- long is signed, so strtol would // return LONG_MAX (== 0x7fffffff on 32-bit archs)) -#define Batoi(str) ((int32_t)strtol(str, NULL, 10)) + +static FORCE_INLINE int32_t atoi_safe(const char *str) { return (int32_t)Bstrtol(str, NULL, 10); } + +#define Batoi(x) atoi_safe(x) #define Batol(str) (strtol(str, NULL, 10)) #define Batof(str) (strtod(str, NULL)) @@ -1166,8 +1169,6 @@ static inline void append_ext_UNSAFE(char *outbuf, const char *ext) ////////// Paths ////////// -char *Bgethomedir(void); - int32_t Bcorrectfilename(char *filename, int32_t removefn); ////////// String manipulation ////////// @@ -1243,8 +1244,21 @@ static FORCE_INLINE void *xaligned_alloc(const bsize_t alignment, const bsize_t void *ptr = Baligned_alloc(alignment, size); return (EDUKE32_PREDICT_TRUE(ptr != NULL)) ? ptr : handle_memerr(ptr); } + +static FORCE_INLINE void *xaligned_calloc(const bsize_t alignment, const bsize_t count, const bsize_t size) +{ + bsize_t const blocksize = count * size; + void *ptr = Baligned_alloc(alignment, blocksize); + if (EDUKE32_PREDICT_TRUE(ptr != NULL)) + { + Bmemset(ptr, 0, blocksize); + return ptr; + } + return handle_memerr(ptr); +} #else # define xaligned_alloc(alignment, size) xmalloc(size) +# define xaligned_calloc(alignment, count, size) xcalloc(count, size) #endif #ifdef DEBUGGINGAIDS @@ -1258,6 +1272,7 @@ static FORCE_INLINE void *xaligned_alloc(const bsize_t alignment, const bsize_t #define Xcalloc(nmemb, size) (EDUKE32_PRE_XALLOC xcalloc(nmemb, size)) #define Xrealloc(ptr, size) (EDUKE32_PRE_XALLOC xrealloc(ptr, size)) #define Xaligned_alloc(alignment, size) (EDUKE32_PRE_XALLOC xaligned_alloc(alignment, size)) +#define Xaligned_calloc(alignment, count, size) (EDUKE32_PRE_XALLOC xaligned_calloc(alignment, count, size)) #define Xfree(ptr) (EDUKE32_PRE_XALLOC xfree(ptr)) #define Xaligned_free(ptr) (EDUKE32_PRE_XALLOC xaligned_free(ptr)) diff --git a/source/build/include/hash.h b/source/build/include/hash.h index 2aac80399..87a050b4b 100644 --- a/source/build/include/hash.h +++ b/source/build/include/hash.h @@ -5,12 +5,13 @@ #define hash_h_ // Hash functions +#define DJB_MAGIC 5381u -typedef struct hashitem_ // size is 12/24 bytes. +typedef struct hashitem // size is 12/24 bytes. { char *string; intptr_t key; - struct hashitem_ *next; + struct hashitem *next; } hashitem_t; typedef struct @@ -22,8 +23,8 @@ typedef struct // djb3 algorithm static inline uint32_t hash_getcode(const char *s) { - uint32_t h = 5381; - int32_t ch; + uint32_t h = DJB_MAGIC; + char ch; while ((ch = Btolower(*s++)) != '\0') h = ((h << 5) + h) ^ ch; @@ -32,49 +33,51 @@ static inline uint32_t hash_getcode(const char *s) } void hash_init(hashtable_t *t); -void hash_loop(hashtable_t *t, void(*func)(const char *, intptr_t)); +void hash_loop(hashtable_t *t, void (*func)(const char *, intptr_t)); void hash_free(hashtable_t *t); -intptr_t hash_findcase(hashtable_t const * t, char const * s); -intptr_t hash_find(hashtable_t const * t, char const * s); void hash_add(hashtable_t *t, const char *s, intptr_t key, int32_t replace); void hash_delete(hashtable_t *t, const char *s); +intptr_t hash_findcase(hashtable_t const *t, char const *s); +intptr_t hash_find(hashtable_t const *t, char const *s); // Hash functions // modified for raw binary keys and one big allocation, and maximum find() performance -typedef struct inthashitem_ +typedef struct inthashitem { intptr_t key; intptr_t value; - struct inthashitem_ *collision; // use NULL to signify empty and pointer identity to signify end of linked list + struct inthashitem *collision; // use NULL to signify empty and pointer identity to signify end of linked list } inthashitem_t; typedef struct { - inthashitem_t * items; + inthashitem_t *items; uint32_t count; } inthashtable_t; // djb3 algorithm static inline uint32_t inthash_getcode(intptr_t key) { - uint32_t h = 5381; + uint32_t h = DJB_MAGIC; - for (uint8_t const * keybuf = (uint8_t *) &key, *const keybuf_end = keybuf + sizeof(intptr_t); keybuf < keybuf_end; ++keybuf) + for (auto keybuf = (uint8_t const *) &key, keybuf_end = keybuf + sizeof(key); keybuf < keybuf_end; ++keybuf) h = ((h << 5) + h) ^ (uint32_t) *keybuf; return h; } void inthash_init(inthashtable_t *t); -void inthash_loop(inthashtable_t const *t, void(*func)(intptr_t, intptr_t)); +void inthash_loop(inthashtable_t const *t, void (*func)(intptr_t, intptr_t)); void inthash_free(inthashtable_t *t); -intptr_t inthash_find(inthashtable_t const *t, intptr_t key); void inthash_add(inthashtable_t *t, intptr_t key, intptr_t value, int32_t replace); void inthash_delete(inthashtable_t *t, intptr_t key); + +intptr_t inthash_find(inthashtable_t const *t, intptr_t key); + // keep the load factor below 0.75 and make sure the size is odd // ideally we would find the next largest prime number #define INTHASH_SIZE(size) ((size * 4u / 3u) | 1u) -#endif +#endif // hash_h_ diff --git a/source/build/include/palette.h b/source/build/include/palette.h index 8bf75b49b..d8b6f0c21 100644 --- a/source/build/include/palette.h +++ b/source/build/include/palette.h @@ -11,7 +11,7 @@ #ifndef palette_h_ #define palette_h_ -#include "cache1d.h" +#include "filesystem/filesystem.h" #define MAXBASEPALS 256 #define MAXPALOOKUPS 256 diff --git a/source/build/include/pragmas.h b/source/build/include/pragmas.h index 922917289..527cb03eb 100644 --- a/source/build/include/pragmas.h +++ b/source/build/include/pragmas.h @@ -189,9 +189,6 @@ void qinterpolatedown16short(intptr_t bufptr, int32_t num, int32_t val, int32_t #ifndef pragmas_have_clearbuf void clearbuf(void *d, int32_t c, int32_t a); #endif -#ifndef pragmas_have_copybuf -void copybuf(const void *s, void *d, int32_t c); -#endif #ifndef pragmas_have_swaps void swapbuf4(void *a, void *b, int32_t c); #endif @@ -199,9 +196,6 @@ void swapbuf4(void *a, void *b, int32_t c); #ifndef pragmas_have_clearbufbyte void clearbufbyte(void *D, int32_t c, int32_t a); #endif -#ifndef pragmas_have_copybufbyte -void copybufbyte(const void *S, void *D, int32_t c); -#endif #ifndef pragmas_have_copybufreverse void copybufreverse(const void *S, void *D, int32_t c); #endif diff --git a/source/build/src/cache1d.cpp b/source/build/src/cache1d.cpp index 9b4dae789..ce903189b 100644 --- a/source/build/src/cache1d.cpp +++ b/source/build/src/cache1d.cpp @@ -6,38 +6,9 @@ // by Jonathon Fowler (jf@jonof.id.au) // by the EDuke32 team (development@voidpoint.com) -#include "compat.h" - -#ifdef _WIN32 -// for FILENAME_CASE_CHECK -# define NEED_SHELLAPI_H -# include "windows_inc.h" -#endif +#include +#include "tarray.h" #include "cache1d.h" -#include "pragmas.h" -#include "baselayer.h" - -uint8_t toupperlookup[256] = -{ - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, - 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, - 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, - 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, - 0x60,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x7b,0x7c,0x7d,0x7e,0x7f, - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, - 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, - 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, - 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, - 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, - 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff -}; - - // Only the sound code still uses this - but it never frees the data. // So we may just toss out the cache and do regular allocations. diff --git a/source/build/src/common.cpp b/source/build/src/common.cpp index 4333aab95..5531f8d81 100644 --- a/source/build/src/common.cpp +++ b/source/build/src/common.cpp @@ -292,7 +292,8 @@ static char* KeyValues_FindKeyValue(char **vdfbuf, char * const vdfbufend, const void Paths_ParseSteamKeyValuesForPaths(const char *vdf, SteamPathParseFunc func) { - FileReader fr = fopenFileReader(vdf, 0); + FileReader fr; + if (!fr.OpenFile(vdf)) return; auto size = fr.GetLength(); char *vdfbuf, *vdfbufend; diff --git a/source/build/src/compat.cpp b/source/build/src/compat.cpp index fdcffc559..7c411ef24 100644 --- a/source/build/src/compat.cpp +++ b/source/build/src/compat.cpp @@ -73,29 +73,6 @@ void set_memerr_handler(void(*handlerfunc)(int32_t, const char *, const char *)) g_MemErrHandler = handlerfunc; } -// -// Stuff which must be a function -// -char *Bgethomedir(void) -{ -#ifdef _WIN32 - - char appdata[MAX_PATH]; - - if (SUCCEEDED(SHGetSpecialFolderPathA(NULL, appdata, CSIDL_APPDATA, FALSE))) - { - return Xstrdup(appdata); - } - return NULL; -#elif defined EDUKE32_OSX - return osx_gethomedir(); -#else - char *e = getenv("HOME"); - if (!e) return NULL; - return Xstrdup(e); -#endif -} - int32_t Bcorrectfilename(char *filename, int32_t removefn) { diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 0d0577e4f..f350dd231 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -306,7 +306,6 @@ static int32_t defsparser(scriptfile *script) } #endif handleevents(); - if (quitevent) return 0; tokn = getatoken(script,basetokens,ARRAY_SIZE(basetokens)); cmdtokptr = script->ltextptr; switch (tokn) @@ -356,7 +355,7 @@ static int32_t defsparser(scriptfile *script) if (scriptfile_getnumber(script,&fnoo)) break; //y-size if (scriptfile_getstring(script,&fn)) break; - if (check_file_exist(fn)) + if (fileSystem.FileExists(fn)) break; tileSetHightileReplacement(tile,pal,fn,-1.0,1.0,1.0,1.0,1.0,0); @@ -374,7 +373,7 @@ static int32_t defsparser(scriptfile *script) { if (scriptfile_getstring(script,&fn[i])) break; //grab the 6 faces - if (check_file_exist(fn[i])) + if (fileSystem.FileExists(fn[i])) happy = 0; } if (i < 6 || !happy) break; @@ -1099,7 +1098,7 @@ static int32_t defsparser(scriptfile *script) if (seenframe) { modelskin = ++lastmodelskin; } seenframe = 0; - if (check_file_exist(skinfn)) + if (fileSystem.FileExists(skinfn)) break; #ifdef USE_OPENGL @@ -1474,7 +1473,7 @@ static int32_t defsparser(scriptfile *script) break; } - if (check_file_exist(skinfn)) + if (fileSystem.FileExists(skinfn)) break; #ifdef USE_OPENGL @@ -1792,7 +1791,7 @@ static int32_t defsparser(scriptfile *script) { if (EDUKE32_PREDICT_FALSE(!fn[i])) initprintf("Error: skybox: missing '%s filename' near line %s:%d\n", skyfaces[i], script->filename, scriptfile_getlinum(script,skyboxtokptr)), happy = 0; // FIXME? - if (check_file_exist(fn[i])) + if (fileSystem.FileExists(fn[i])) happy = 0; } if (!happy) break; @@ -1847,7 +1846,7 @@ static int32_t defsparser(scriptfile *script) break; } - if (check_file_exist(fn)) + if (fileSystem.FileExists(fn)) break; } @@ -2102,7 +2101,7 @@ static int32_t defsparser(scriptfile *script) break; } - if (EDUKE32_PREDICT_FALSE(check_file_exist(fn))) + if (EDUKE32_PREDICT_FALSE(fileSystem.FileExists(fn))) break; if (xsiz > 0 && ysiz > 0) @@ -2165,7 +2164,7 @@ static int32_t defsparser(scriptfile *script) break; } - if (EDUKE32_PREDICT_FALSE(check_file_exist(fn))) + if (EDUKE32_PREDICT_FALSE(fileSystem.FileExists(fn))) break; switch (token) @@ -2597,7 +2596,7 @@ static int32_t defsparser(scriptfile *script) break; } - FileReader fil = kopenFileReader(fn, 0); + FileReader fil = fileSystem.OpenFileReader(fn, 0); if (!fil.isOpen()) { initprintf("Error: basepalette: Failed opening \"%s\" on line %s:%d\n", fn, @@ -2771,7 +2770,7 @@ static int32_t defsparser(scriptfile *script) break; } - FileReader fil = kopenFileReader(fn, 0); + FileReader fil = fileSystem.OpenFileReader(fn, 0); if (!fil.isOpen()) { initprintf("Error: palookup: Failed opening \"%s\" on line %s:%d\n", fn, @@ -3064,7 +3063,7 @@ static int32_t defsparser(scriptfile *script) break; } - FileReader fil = kopenFileReader(fn, 0); + FileReader fil = fileSystem.OpenFileReader(fn, 0); if (!fil.isOpen()) { initprintf("Error: blendtable: Failed opening \"%s\" on line %s:%d\n", fn, diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index af0307b22..333f804fe 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -24,8 +24,10 @@ #include "gamecvars.h" #include "c_console.h" #include "v_2ddrawer.h" +#include "v_draw.h" #include "imgui.h" #include "stats.h" +#include "menu.h" #ifdef USE_OPENGL # include "glsurface.h" @@ -157,7 +159,8 @@ int32_t globaltilesizy; int32_t globalx1, globaly2, globalx3, globaly3; int32_t sloptable[SLOPTABLESIZ]; -static intptr_t slopalookup[16384]; // was 2048 +#define SLOPALOOKUPSIZ 16384 +static intptr_t slopalookup[SLOPALOOKUPSIZ]; // was 2048 static int32_t no_radarang2 = 0; static int16_t radarang[1280]; @@ -3387,7 +3390,7 @@ static void fgrouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) int32_t i, j, l, globalx1, globaly1, y1, y2, daslope, daz, wxi, wyi; float fi, wx, wy, dasqr; float globalx, globaly, globalx2, globaly2, globalx3, globaly3, globalz, globalzd, globalzx; - int32_t shoffs, m1, m2; + int32_t shoffs, m1, m2, shy1, shy2; intptr_t *mptr1, *mptr2; const usectortype *const sec = (usectortype *)§or[sectnum]; @@ -3521,7 +3524,14 @@ static void fgrouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) //Avoid visibility overflow by crossing horizon m1 += klabs(l); m2 = m1+l; - mptr1 = (intptr_t *)&slopalookup[y1+(shoffs>>15)]; mptr2 = mptr1+1; + shy1 = y1+(shoffs>>15); + if ((unsigned)shy1 >= SLOPALOOKUPSIZ-1) + { + OSD_Printf("%s:%d: slopalookup[%" PRId32 "] overflow drawing sector %d!\n", EDUKE32_FUNCTION, __LINE__, shy1, sectnum); + return; + } + + mptr1 = &slopalookup[shy1]; mptr2 = mptr1+1; for (int x=dax1; x<=dax2; x++) { @@ -3529,8 +3539,23 @@ static void fgrouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) else { y1 = max(umost[x],dplc[x]); y2 = dmost[x]-1; } if (y1 <= y2) { - intptr_t *nptr1 = &slopalookup[y1+(shoffs>>15)]; - intptr_t *nptr2 = &slopalookup[y2+(shoffs>>15)]; + shy1 = y1+(shoffs>>15); + shy2 = y2+(shoffs>>15); + + // Ridiculously steep gradient? + if ((unsigned)shy1 >= SLOPALOOKUPSIZ) + { + OSD_Printf("%s:%d: slopalookup[%" PRId32 "] overflow drawing sector %d!\n", EDUKE32_FUNCTION, __LINE__, shy1, sectnum); + goto next_most; + } + if ((unsigned)shy2 >= SLOPALOOKUPSIZ) + { + OSD_Printf("%s:%d: slopalookup[%" PRId32 "] overflow drawing sector %d!\n", EDUKE32_FUNCTION, __LINE__, shy2, sectnum); + goto next_most; + } + + intptr_t *nptr1 = &slopalookup[shy1]; + intptr_t *nptr2 = &slopalookup[shy2]; while (nptr1 <= mptr1) { @@ -3660,6 +3685,7 @@ static void fgrouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) #undef LINTERPSIZ if ((x&15) == 0) faketimerhandler(); } +next_most: globalx2 += globalx; globaly2 += globaly; globalzx += globalz; @@ -3676,7 +3702,7 @@ static void grouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) } int32_t i, l, x, y, dx, dy, wx, wy, y1, y2, daz; int32_t daslope, dasqr; - int32_t shoffs, m1, m2; + int32_t shoffs, m1, m2, shy1, shy2; intptr_t *mptr1, *mptr2, j; // Er, yes, they're not global anymore: @@ -3808,7 +3834,14 @@ static void grouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) //Avoid visibility overflow by crossing horizon m1 += klabs((int32_t) (globalzd>>16)); m2 = m1+l; - mptr1 = (intptr_t *)&slopalookup[y1+(shoffs>>15)]; mptr2 = mptr1+1; + shy1 = y1+(shoffs>>15); + if ((unsigned)shy1 >= SLOPALOOKUPSIZ - 1) + { + OSD_Printf("%s:%d: slopalookup[%" PRId32 "] overflow drawing sector %d!\n", EDUKE32_FUNCTION, __LINE__, shy1, sectnum); + return; + } + + mptr1 = &slopalookup[shy1]; mptr2 = mptr1+1; for (x=dax1; x<=dax2; x++) { @@ -3816,8 +3849,23 @@ static void grouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) else { y1 = max(umost[x],dplc[x]); y2 = dmost[x]-1; } if (y1 <= y2) { - intptr_t *nptr1 = &slopalookup[y1+(shoffs>>15)]; - intptr_t *nptr2 = &slopalookup[y2+(shoffs>>15)]; + shy1 = y1+(shoffs>>15); + shy2 = y2+(shoffs>>15); + + // Ridiculously steep gradient? + if ((unsigned)shy1 >= SLOPALOOKUPSIZ) + { + OSD_Printf("%s:%d: slopalookup[%" PRId32 "] overflow drawing sector %d!\n", EDUKE32_FUNCTION, __LINE__, shy1, sectnum); + goto next_most; + } + if ((unsigned)shy2 >= SLOPALOOKUPSIZ) + { + OSD_Printf("%s:%d: slopalookup[%" PRId32 "] overflow drawing sector %d!\n", EDUKE32_FUNCTION, __LINE__, shy2, sectnum); + goto next_most; + } + + intptr_t *nptr1 = &slopalookup[shy1]; + intptr_t *nptr2 = &slopalookup[shy2]; while (nptr1 <= mptr1) { @@ -3849,6 +3897,7 @@ static void grouscan(int32_t dax1, int32_t dax2, int32_t sectnum, char dastat) if ((x&15) == 0) faketimerhandler(); } +next_most: globalx2 += globalx; globaly2 += globaly; globalzx += globalz; @@ -4429,7 +4478,7 @@ static void classicDrawBunches(int32_t bunch) smostwall[smostwallcnt] = z; smostwalltype[smostwallcnt] = 1; //1 for umost smostwallcnt++; - copybufbyte(&umost[x1],&smost[smostcnt],i*sizeof(smost[0])); + memcpy(&umost[x1],&smost[smostcnt],i*sizeof(smost[0])); smostcnt += i; } } @@ -4515,7 +4564,7 @@ static void classicDrawBunches(int32_t bunch) smostwall[smostwallcnt] = z; smostwalltype[smostwallcnt] = 2; //2 for dmost smostwallcnt++; - copybufbyte(&dmost[x1],&smost[smostcnt],i*sizeof(smost[0])); + memcpy(&dmost[x1],&smost[smostcnt],i*sizeof(smost[0])); smostcnt += i; } } @@ -4984,16 +5033,6 @@ static void classicDrawVoxel(int32_t dasprx, int32_t daspry, int32_t dasprz, int } } -#if 0 - for (x=0; x=0 && daumost[x]=0 && dadmost[x]=0 && !bitmap_test(excludesectbitmap, sectnum) && inside_p(x, y, sectnum)); } /* NOTE: no bound check */ -static inline bool inside_z_p(int32_t const x, int32_t const y, int32_t const z, int const sectnum) +static inline int inside_z_p(int32_t const x, int32_t const y, int32_t const z, int const sectnum) { int32_t cz, fz; getzsofslope(sectnum, x, y, &cz, &fz); @@ -11396,6 +11430,9 @@ void renderFlushPerms(void) } +bool rotatesprite_2doverride; // gross hack alert. Thanks to the insufficient abstraction the only chance to redirect rotatesprite calls + // to the 2D drawer is to use a global flag and check in rotatesprite_. +#include "v_2ddrawer.h" // // rotatesprite // @@ -11413,6 +11450,12 @@ void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, tileUpdatePicnum(&picnum, (int16_t)0xc000); if ((tilesiz[picnum].x <= 0) || (tilesiz[picnum].y <= 0)) return; + if (rotatesprite_2doverride) + { + twod.rotatesprite(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, cx1, cy1, cx2, cy2); + return; + } + // Experimental / development bits. ONLY FOR INTERNAL USE! // bit RS_CENTERORIGIN: see dorotspr_handle_bit2 //////////////////// @@ -11594,8 +11637,8 @@ void renderSetTarget(int16_t tilenume, int32_t xsiz, int32_t ysiz) rendmode = REND_CLASSIC; #endif - copybufbyte(&startumost[windowxy1.x],&bakumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakumost[0])); - copybufbyte(&startdmost[windowxy1.x],&bakdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakdmost[0])); + memcpy(&startumost[windowxy1.x],&bakumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakumost[0])); + memcpy(&startdmost[windowxy1.x],&bakdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakdmost[0])); setviewcnt++; offscreenrendering = 1; @@ -11629,8 +11672,8 @@ void renderRestoreTarget(void) ydim = bakysiz[setviewcnt]; videoSetViewableArea(bakwindowxy1[setviewcnt].x,bakwindowxy1[setviewcnt].y, bakwindowxy2[setviewcnt].x,bakwindowxy2[setviewcnt].y); - copybufbyte(&bakumost[windowxy1.x],&startumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startumost[0])); - copybufbyte(&bakdmost[windowxy1.x],&startdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startdmost[0])); + memcpy(&bakumost[windowxy1.x],&startumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startumost[0])); + memcpy(&bakdmost[windowxy1.x],&startdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startdmost[0])); frameplace = bakframeplace[setviewcnt]; calc_ylookup((setviewcnt == 0) ? bytesperline : bakxsiz[setviewcnt], @@ -12066,42 +12109,6 @@ void setfirstwall(int16_t sectnum, int16_t newfirstwall) Xfree(tmpwall); } -// -// qsetmodeany -// -void videoSet2dMode(int32_t daxdim, int32_t daydim) -{ - if (daxdim < 640) daxdim = 640; - if (daydim < 480) daydim = 480; - - if (qsetmode != ((daxdim<<16)|(daydim&0xffff))) - { - g_lastpalettesum = 0; - if (videoSetMode(daxdim, daydim, 8, fullscreen) < 0) - return; - - xdim = xres; - ydim = yres; - -#ifdef USE_OPENGL - fxdim = (float) xdim; - fydim = (float) ydim; - - rendmode = REND_CLASSIC; -#endif - videoAllocateBuffers(); - - ydim16 = ydim - STATUS2DSIZ2; - halfxdim16 = xdim >> 1; - midydim16 = ydim16 >> 1; // scale(200,ydim,480); - - videoBeginDrawing(); //{{{ - Bmemset((char *)frameplace, 0, ydim*bytesperline); - videoEndDrawing(); //}}} - } - - qsetmode = ((daxdim<<16)|(daydim&0xffff)); -} static int32_t printext_checkypos(int32_t ypos, int32_t *yminptr, int32_t *ymaxptr) { diff --git a/source/build/src/hash.cpp b/source/build/src/hash.cpp index 6b2b804fc..a7c4db450 100644 --- a/source/build/src/hash.cpp +++ b/source/build/src/hash.cpp @@ -6,69 +6,63 @@ void hash_init(hashtable_t *t) { hash_free(t); - t->items=(hashitem_t **) Xcalloc(1, t->size * sizeof(hashitem_t)); + t->items = (hashitem_t **) Xaligned_calloc(16, t->size, sizeof(hashitem_t)); } void hash_loop(hashtable_t *t, void(*func)(const char *, intptr_t)) { - if (t->items == NULL) + if (t->items == nullptr) return; - for (bssize_t i=0; i < t->size; i++) - for (hashitem_t *item=t->items[i]; item != NULL; item = item->next) + for (native_t i=0; i < t->size; i++) + for (auto item = t->items[i]; item != nullptr; item = item->next) func(item->string, item->key); } void hash_free(hashtable_t *t) { - if (t == NULL || t->items == NULL) + if (t->items == nullptr) return; int remaining = t->size - 1; do { - hashitem_t *cur = t->items[remaining]; + auto cur = t->items[remaining]; while (cur) { - hashitem_t * const tmp = cur; + auto tmp = cur; cur = cur->next; Xfree(tmp->string); - Xfree(tmp); + Xaligned_free(tmp); } } while (--remaining >= 0); - DO_FREE_AND_NULL(t->items); + ALIGNED_FREE_AND_NULL(t->items); } void hash_add(hashtable_t *t, const char *s, intptr_t key, int32_t replace) { #ifdef DEBUGGINGAIDS - Bassert(t->items != NULL); -#else - if (EDUKE32_PREDICT_FALSE(t->items == NULL)) - { - initprintf("hash_add(): table not initialized!\n"); - return; - } + Bassert(t->items != nullptr); #endif - - uint32_t code = hash_getcode(s) % t->size; - hashitem_t *cur = t->items[code]; + uint32_t const code = hash_getcode(s) % t->size; + auto cur = t->items[code]; if (!cur) { - cur = (hashitem_t *) Xcalloc(1, sizeof(hashitem_t)); + cur = (hashitem_t *) Xaligned_alloc(16, sizeof(hashitem_t)); cur->string = Xstrdup(s); - cur->key = key; - cur->next = NULL; + cur->key = key; + cur->next = nullptr; + t->items[code] = cur; return; } - hashitem_t *prev = NULL; + hashitem_t *prev = nullptr; do { @@ -80,10 +74,11 @@ void hash_add(hashtable_t *t, const char *s, intptr_t key, int32_t replace) prev = cur; } while ((cur = cur->next)); - cur = (hashitem_t *) Xcalloc(1, sizeof(hashitem_t)); + cur = (hashitem_t *) Xaligned_alloc(16, sizeof(hashitem_t)); cur->string = Xstrdup(s); - cur->key = key; - cur->next = NULL; + cur->key = key; + cur->next = nullptr; + prev->next = cur; } @@ -91,22 +86,15 @@ void hash_add(hashtable_t *t, const char *s, intptr_t key, int32_t replace) void hash_delete(hashtable_t *t, const char *s) { #ifdef DEBUGGINGAIDS - Bassert(t->items != NULL); -#else - if (t->items == NULL) - { - initprintf("hash_delete(): table not initialized!\n"); - return; - } + Bassert(t->items != nullptr); #endif - - uint32_t code = hash_getcode(s) % t->size; - hashitem_t *cur = t->items[code]; + uint32_t const code = hash_getcode(s) % t->size; + auto cur = t->items[code]; if (!cur) return; - hashitem_t *prev = NULL; + hashitem_t *prev = nullptr; do { @@ -119,7 +107,7 @@ void hash_delete(hashtable_t *t, const char *s) else prev->next = cur->next; - Xfree(cur); + Xaligned_free(cur); break; } @@ -130,16 +118,9 @@ void hash_delete(hashtable_t *t, const char *s) intptr_t hash_find(const hashtable_t * const t, char const * const s) { #ifdef DEBUGGINGAIDS - Bassert(t->items != NULL); -#else - if (t->items == NULL) - { - initprintf("hash_find(): table not initialized!\n"); - return -1; - } + Bassert(t->items != nullptr); #endif - - hashitem_t *cur = t->items[hash_getcode(s) % t->size]; + auto cur = t->items[hash_getcode(s) % t->size]; if (!cur) return -1; @@ -155,16 +136,9 @@ intptr_t hash_find(const hashtable_t * const t, char const * const s) intptr_t hash_findcase(const hashtable_t * const t, char const * const s) { #ifdef DEBUGGINGAIDS - Bassert(t->items != NULL); -#else - if (t->items == NULL) - { - initprintf("hash_findcase(): table not initialized!\n"); - return -1; - } + Bassert(t->items != nullptr); #endif - - hashitem_t *cur = t->items[hash_getcode(s) % t->size]; + auto cur = t->items[hash_getcode(s) % t->size]; if (!cur) return -1; @@ -178,60 +152,36 @@ intptr_t hash_findcase(const hashtable_t * const t, char const * const s) } +void inthash_free(inthashtable_t *t) { ALIGNED_FREE_AND_NULL(t->items); } + void inthash_init(inthashtable_t *t) { - if (EDUKE32_PREDICT_FALSE(!t->count)) - { - initputs("inthash_add(): count is zero!\n"); - return; - } - inthash_free(t); - - t->items = (inthashitem_t *) Xcalloc(t->count, sizeof(inthashitem_t)); + t->items = (inthashitem_t *) Xaligned_calloc(16, t->count, sizeof(inthashitem_t)); } void inthash_loop(inthashtable_t const *t, void(*func)(intptr_t, intptr_t)) { -#ifdef DEBUGGINGAIDS - Bassert(t->items != NULL); -#else - if (EDUKE32_PREDICT_FALSE(t->items == NULL)) - { - initputs("inthash_loop(): table not initialized!\n"); + if (t->items == nullptr) return; - } -#endif - for (inthashitem_t const * item = t->items, *const items_end = t->items + t->count; item < items_end; ++item) + for (auto *item = t->items, *const items_end = t->items + t->count; item < items_end; ++item) func(item->key, item->value); } -void inthash_free(inthashtable_t *t) -{ - DO_FREE_AND_NULL(t->items); -} void inthash_add(inthashtable_t *t, intptr_t key, intptr_t value, int32_t replace) { #ifdef DEBUGGINGAIDS - Bassert(t->items != NULL); -#else - if (EDUKE32_PREDICT_FALSE(t->items == NULL)) - { - initputs("inthash_add(): table not initialized!\n"); - return; - } + Bassert(t->items != nullptr); #endif + auto seeker = t->items + inthash_getcode(key) % t->count; - inthashitem_t * seeker = t->items + inthash_getcode(key) % t->count; - - if (seeker->collision == NULL) + if (seeker->collision == nullptr) { seeker->key = key; seeker->value = value; seeker->collision = seeker; - return; } @@ -254,17 +204,14 @@ void inthash_add(inthashtable_t *t, intptr_t key, intptr_t value, int32_t replac } } - inthashitem_t *tail = seeker; + auto tail = seeker; do tail = t->items + (tail - t->items + 1) % t->count; - while (tail->collision != NULL && tail != seeker); + while (tail->collision != nullptr && tail != seeker); if (EDUKE32_PREDICT_FALSE(tail == seeker)) - { - initputs("inthash_add(): table full!\n"); - return; - } + I_Error("inthash_add(): table full!\n"); tail->key = key; tail->value = value; @@ -275,35 +222,25 @@ void inthash_add(inthashtable_t *t, intptr_t key, intptr_t value, int32_t replac void inthash_delete(inthashtable_t *t, intptr_t key) { #ifdef DEBUGGINGAIDS - Bassert(t->items != NULL); -#else - if (EDUKE32_PREDICT_FALSE(t->items == NULL)) - { - initputs("inthash_delete(): table not initialized!\n"); - return; - } + Bassert(t->items != nullptr); #endif + auto seeker = t->items + inthash_getcode(key) % t->count; - inthashitem_t * seeker = t->items + inthash_getcode(key) % t->count; - - if (seeker->collision == NULL) - return; - - if (seeker->key == key) + if (seeker->collision == nullptr || seeker->key == key) { - seeker->collision = NULL; + seeker->collision = nullptr; return; } while (seeker != seeker->collision) { - inthashitem_t * const prev = seeker; + auto prev = seeker; seeker = seeker->collision; if (seeker->key == key) { prev->collision = seeker == seeker->collision ? prev : seeker->collision; - seeker->collision = NULL; + seeker->collision = nullptr; return; } } @@ -312,18 +249,11 @@ void inthash_delete(inthashtable_t *t, intptr_t key) intptr_t inthash_find(inthashtable_t const *t, intptr_t key) { #ifdef DEBUGGINGAIDS - Bassert(t->items != NULL); -#else - if (EDUKE32_PREDICT_FALSE(t->items == NULL)) - { - initputs("inthash_find(): table not initialized!\n"); - return -1; - } + Bassert(t->items != nullptr); #endif + auto seeker = t->items + inthash_getcode(key) % t->count; - inthashitem_t const * seeker = t->items + inthash_getcode(key) % t->count; - - if (seeker->collision == NULL) + if (seeker->collision == nullptr) return -1; if (seeker->key == key) diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp index 5fd32bd5d..a7d1191e0 100644 --- a/source/build/src/mdsprite.cpp +++ b/source/build/src/mdsprite.cpp @@ -1862,7 +1862,7 @@ mdmodel_t *mdload(const char *filnam) vm = (mdmodel_t *)voxload(filnam); if (vm) return vm; - auto fil = kopenFileReader(filnam,0); + auto fil = fileSystem.OpenFileReader(filnam,0); if (!fil.isOpen()) return NULL; diff --git a/source/build/src/palette.cpp b/source/build/src/palette.cpp index bf09f3372..0a38ad35b 100644 --- a/source/build/src/palette.cpp +++ b/source/build/src/palette.cpp @@ -178,7 +178,7 @@ void paletteLoadFromDisk(void) return; } - auto fil = kopenFileReader("palette.dat", 0); + auto fil = fileSystem.OpenFileReader("palette.dat", 0); if (!fil.isOpen()) return; diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 4374b6644..1a70867e3 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -697,7 +697,7 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32 skyzbufferhack_pass--; } - if (!tilePtr(globalpicnum)) + if (!success) GLInterface.SetColorMask(true); } diff --git a/source/build/src/pragmas.cpp b/source/build/src/pragmas.cpp index 219849540..1d81f48e6 100644 --- a/source/build/src/pragmas.cpp +++ b/source/build/src/pragmas.cpp @@ -71,17 +71,6 @@ void clearbuf(void *d, int32_t c, int32_t a) } #endif -#ifndef pragmas_have_copybuf -void copybuf(const void *s, void *d, int32_t c) -{ - auto p = (const int32_t *) s; - auto q = (int32_t *) d; - - while (c--) - *q++ = *p++; -} -#endif - #ifndef pragmas_have_swaps void swapbuf4(void *a, void *b, int32_t c) { @@ -113,16 +102,6 @@ void clearbufbyte(void *D, int32_t c, int32_t a) } #endif -#ifndef pragmas_have_copybufbyte -void copybufbyte(const void *s, void *d, int32_t c) -{ - auto src = (const char *)s; - auto dst = (char *)d; - - while (c--) - *dst++ = *src++; -} -#endif // copybufreverse() is a special case: use the assembly version for GCC on x86 diff --git a/source/build/src/screenshot.cpp b/source/build/src/screenshot.cpp index 3a6de4d2e..21f8649d5 100644 --- a/source/build/src/screenshot.cpp +++ b/source/build/src/screenshot.cpp @@ -8,6 +8,7 @@ #include "cmdlib.h" #include "gamecontrol.h" #include "printf.h" +#include "c_dispatch.h" #include "../../glbackend/glbackend.h" @@ -156,5 +157,10 @@ int videoCaptureScreen() return 0; } +CCMD(screenshot) +{ + videoCaptureScreen(); +} + #undef HICOLOR diff --git a/source/build/src/scriptfile.cpp b/source/build/src/scriptfile.cpp index dd1fa5f88..e6103e68e 100644 --- a/source/build/src/scriptfile.cpp +++ b/source/build/src/scriptfile.cpp @@ -9,7 +9,7 @@ #include "scriptfile.h" #include "baselayer.h" #include "compat.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" #define ISWS(x) ((x == ' ') || (x == '\t') || (x == '\r') || (x == '\n')) @@ -299,7 +299,7 @@ void scriptfile_preparse(scriptfile *sf, char *tx, int32_t flen) scriptfile *scriptfile_fromfile(const char *fn) { - auto fr = kopenFileReader(fn, 0); + auto fr = fileSystem.OpenFileReader(fn, 0); if (!fr.isOpen()) return nullptr; uint32_t flen = fr.GetLength(); diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp index 85fa9c0f0..98ff65568 100644 --- a/source/build/src/sdlayer.cpp +++ b/source/build/src/sdlayer.cpp @@ -33,10 +33,14 @@ #include "i_time.h" #include "c_dispatch.h" #include "d_gui.h" +#include "menu.h" #include "utf8.h" #include "imgui.h" #include "imgui_impl_sdl.h" #include "imgui_impl_opengl3.h" + + + #ifndef NETCODE_DISABLE #include "enet.h" #endif @@ -98,8 +102,9 @@ unsigned char syncstate; // fix for mousewheel int32_t inputchecked = 0; +bool screenshot_requested; -char quitevent=0, appactive=1, novideo=0; +char appactive=1, novideo=0; // video static SDL_Surface *sdl_surface/*=NULL*/; @@ -662,8 +667,8 @@ static SDL_GameController *controller = NULL; static void LoadSDLControllerDB() { - auto fh = fopenFileReader("gamecontrollerdb.txt", 0); - if (!fh.isOpen()) + FileReader fh; + if (!fh.OpenFile("gamecontrollerdb.txt")) return; int flen = fh.GetLength(); @@ -743,8 +748,10 @@ void joyScanDevices() buildprintf("Using controller %s\n", SDL_GameControllerName(controller)); joystick.numAxes = SDL_CONTROLLER_AXIS_MAX; + joystick.numBalls = 0; joystick.numButtons = SDL_CONTROLLER_BUTTON_MAX; joystick.numHats = 0; + joystick.isGameController = 1; Xfree(joystick.pAxis); @@ -767,11 +774,15 @@ void joyScanDevices() // KEEPINSYNC duke3d/src/gamedefs.h, mact/include/_control.h joystick.numAxes = min(9, SDL_JoystickNumAxes(joydev)); + joystick.numBalls = SDL_JoystickNumBalls(joydev); joystick.numButtons = min(32, SDL_JoystickNumButtons(joydev)); - joystick.numHats = min((36-joystick.numButtons)/4,SDL_JoystickNumHats(joydev)); + joystick.numHats = min((36 - joystick.numButtons) / 4, SDL_JoystickNumHats(joydev)); + joystick.isGameController = 0; - initprintf("Joystick %d has %d axes, %d buttons, and %d hat(s).\n", i+1, joystick.numAxes, joystick.numButtons, joystick.numHats); + buildprint("Joystick ", i+1, " has ", joystick.numAxes, " axes, ", joystick.numButtons, " buttons, ", + (joystick.numHats ? std::to_string(joystick.numHats).c_str() : "no"), " hats, and ", + (joystick.numBalls ? std::to_string(joystick.numBalls).c_str() : "no"), " balls.\n"); Xfree(joystick.pAxis); joystick.pAxis = (int32_t *)Xcalloc(joystick.numAxes, sizeof(int32_t)); @@ -959,18 +970,9 @@ void mouseGrabInput(bool grab) g_mouseGrabbed = grab; inputState.MouseSetPos(0, 0); -} - -void mouseLockToWindow(char a) -{ - if (!(a & 2)) - { - mouseGrabInput(a); - g_mouseLockedToWindow = g_mouseGrabbed; - } - - // Fixme - SDL_ShowCursor(GUICapture ? SDL_ENABLE : SDL_DISABLE); + SDL_ShowCursor(!grab ? SDL_ENABLE : SDL_DISABLE); + if (grab) GUICapture &= ~1; + else GUICapture |= 1; } // @@ -1663,6 +1665,7 @@ int32_t handleevents_sdlcommon(SDL_Event *ev) switch (ev->type) { case SDL_MOUSEMOTION: + //case SDL_JOYBALLMOTION: { // The menus need this, even in non GUI-capture mode event_t event; @@ -1706,8 +1709,27 @@ int32_t handleevents_sdlcommon(SDL_Event *ev) if (j < 0) break; - event_t evt = { uint8_t((ev->button.state == SDL_PRESSED)? EV_KeyDown : EV_KeyUp), 0, (int16_t)j}; - D_PostEvent(&evt); + if (!(GUICapture & 1)) + { + event_t evt = { uint8_t((ev->button.state == SDL_PRESSED) ? EV_KeyDown : EV_KeyUp), 0, (int16_t)j }; + D_PostEvent(&evt); + } + else + { + event_t evt; + evt.type = EV_GUI_Event; + evt.subtype = uint8_t((ev->button.state == SDL_PRESSED) ? EV_GUI_LButtonDown : EV_GUI_LButtonUp); + evt.data1 = ev->motion.x; + evt.data2 = ev->motion.y; + + SDL_Keymod kmod = SDL_GetModState(); + evt.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | + ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | + ((kmod & KMOD_ALT) ? GKM_ALT : 0); + + D_PostEvent(&evt); + + } break; } @@ -1779,7 +1801,7 @@ int32_t handleevents_sdlcommon(SDL_Event *ev) break; case SDL_QUIT: - quitevent = 1; + throw ExitEvent(0); // completely bypass the hackery in the games to block Alt-F4. return -1; } @@ -1890,7 +1912,7 @@ int32_t handleevents_pollsdl(void) { code = ev.text.text[j]; // Fixme: Send an EV_GUI_Event instead and properly deal with Unicode. - if (GUICapture & 1) + if ((GUICapture & 1) && menuactive != MENU_WaitKey) { event_t ev = { EV_GUI_Event, EV_GUI_Char, int16_t(j), !!(SDL_GetModState() & KMOD_ALT) }; D_PostEvent(&ev); @@ -1902,7 +1924,7 @@ int32_t handleevents_pollsdl(void) case SDL_KEYDOWN: case SDL_KEYUP: { - if (GUICapture & 1) + if ((GUICapture & 1) && menuactive != MENU_WaitKey) { event_t event = {}; event.type = EV_GUI_Event; @@ -2060,6 +2082,17 @@ int32_t handleevents(void) return rv; } +void I_SetMouseCapture() +{ + // Clear out any mouse movement. + SDL_CaptureMouse(SDL_TRUE); +} + +void I_ReleaseMouseCapture() +{ + SDL_CaptureMouse(SDL_FALSE); +} + auto vsnprintfptr = vsnprintf; // This is an inline in Visual Studio but we need an address for it to satisfy the MinGW compiled libraries. // @@ -2078,3 +2111,4 @@ void debugprintf(const char* f, ...) OutputDebugStringA(buf); } + diff --git a/source/build/src/timer.cpp b/source/build/src/timer.cpp index 0d1b343fa..8fc00ade3 100644 --- a/source/build/src/timer.cpp +++ b/source/build/src/timer.cpp @@ -52,10 +52,17 @@ ATTRIBUTE((flatten)) void timerUpdateClock(void) totalclock += n; timerlastsample += n*nanoseconds(1000000000/timerticspersec); + // This function can get called from deep within processing loops. + // The callbacks in here may not be called recursively, though. + static bool recursion; + if (recursion) return; + recursion = true; + for (; n > 0; n--) { for (auto cb : callbacks) cb(); } + recursion = false; } void(*timerSetCallback(void(*callback)(void)))(void) diff --git a/source/build/src/voxmodel.cpp b/source/build/src/voxmodel.cpp index 7bb7f7650..112f1d1c8 100644 --- a/source/build/src/voxmodel.cpp +++ b/source/build/src/voxmodel.cpp @@ -607,7 +607,7 @@ static void read_pal(FileReader &fil, int32_t pal[256]) static int32_t loadvox(const char *filnam) { - auto fil = kopenFileReader(filnam, 0); + auto fil = fileSystem.OpenFileReader(filnam, 0); if (!fil.isOpen()) return -1; @@ -683,7 +683,7 @@ static int32_t loadkvx(const char *filnam) { int32_t i, mip1leng; - auto fil = kopenFileReader(filnam, 0); + auto fil = fileSystem.OpenFileReader(filnam, 0); if (!fil.isOpen()) return -1; @@ -767,7 +767,7 @@ static int32_t loadkv6(const char *filnam) { int32_t i; - auto fil = kopenFileReader(filnam, 0); + auto fil = fileSystem.OpenFileReader(filnam, 0); if (!fil.isOpen()) return -1; diff --git a/source/common/2d/v_2ddrawer.cpp b/source/common/2d/v_2ddrawer.cpp index bdc0da2f5..92b499f06 100644 --- a/source/common/2d/v_2ddrawer.cpp +++ b/source/common/2d/v_2ddrawer.cpp @@ -31,6 +31,7 @@ #include "renderstyle.h" #include "drawparms.h" #include "vectors.h" +#include "gamecvars.h" //#include "doomtype.h" #include "templates.h" //#include "r_utility.h" @@ -554,3 +555,49 @@ void F2DDrawer::Clear() mData.Clear(); mIsFirstPass = true; } + +//========================================================================== +// +// +// +//========================================================================== + + +#include "build.h" +#include "../src/engine_priv.h" + +void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, + int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, + int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2) +{ + if (r_rotatespritenowidescreen) + { + dastat |= RS_STRETCH; + dastat &= ~RS_ALIGN_MASK; + } + + // This is mainly a hack because the rotatesprite code is far too messed up to integrate into the 2D drawer. + // This merely stores the parameters and later just calls polymost_rotatesprite do do the work. + // Cleanup can be done once everything is working - but for the menu's transition the original calls should be preserved. + RenderCommand dg; + + dg.mType = DrawTypeRotateSprite; + + // Just store the values in the otherwise useless fields of the draw command instead of allocating separate memory. + dg.mVertIndex = sx; + dg.mVertCount = sy; + dg.mIndexIndex = z; + dg.mIndexCount = a; + dg.mSpecialColormap[0].d = picnum; + dg.mRemapIndex = dashade; + dg.mFlags = dapalnum; + dg.mSpecialColormap[1].d = dastat; + dg.mDesaturate = daalpha; + dg.mColor1.d = dablend; + dg.mScissor[0] = cx1; + dg.mScissor[1] = cy1; + dg.mScissor[2] = cx2; + dg.mScissor[3] = cy2; + mData.Push(dg); // don't even try to merge. +} + diff --git a/source/common/2d/v_2ddrawer.h b/source/common/2d/v_2ddrawer.h index 8e2d52e6e..0641d42b1 100644 --- a/source/common/2d/v_2ddrawer.h +++ b/source/common/2d/v_2ddrawer.h @@ -19,6 +19,7 @@ public: DrawTypeTriangles, DrawTypeLines, DrawTypePoints, + DrawTypeRotateSprite, }; enum ETextureFlags : uint8_t @@ -85,7 +86,7 @@ public: bool isCompatible(const RenderCommand &other) const { return mTexture == other.mTexture && - mType == other.mType && + mType == other.mType && mType != DrawTypeRotateSprite && mRemapIndex == other.mRemapIndex && mSpecialColormap[0].d == other.mSpecialColormap[0].d && mSpecialColormap[1].d == other.mSpecialColormap[1].d && @@ -122,6 +123,10 @@ public: void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha = 255); void AddPixel(int x1, int y1, uint32_t color); + void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, + int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, + int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2); + void Clear(); bool mIsFirstPass = true; diff --git a/source/common/2d/v_draw.cpp b/source/common/2d/v_draw.cpp index 0b44e95d8..3de2fbded 100644 --- a/source/common/2d/v_draw.cpp +++ b/source/common/2d/v_draw.cpp @@ -107,6 +107,36 @@ int CleanWidth, CleanHeight; int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1; +void V_UpdateModeSize(int width, int height) +{ + // This calculates the menu scale. + // The optimal scale will always be to fit a virtual 640 pixel wide display onto the screen. + // Exceptions are made for a few ranges where the available virtual width is > 480. + + // This reference size is being used so that on 800x450 (small 16:9) a scale of 2 gets used. + + CleanXfac = std::max(std::min(screen->GetWidth() / 400, screen->GetHeight() / 240), 1); + if (CleanXfac >= 4) CleanXfac--; // Otherwise we do not have enough space for the episode/skill menus in some languages. + CleanYfac = CleanXfac; + CleanWidth = screen->GetWidth() / CleanXfac; + CleanHeight = screen->GetHeight() / CleanYfac; + + int w = screen->GetWidth(); + int factor; + if (w < 640) factor = 1; + else if (w >= 1024 && w < 1280) factor = 2; + else if (w >= 1600 && w < 1920) factor = 3; + else factor = w / 640; + + if (w < 1360) factor = 1; + else if (w < 1920) factor = 2; + else factor = int(factor * 0.7); + + CleanYfac_1 = CleanXfac_1 = factor;// MAX(1, int(factor * 0.7)); + CleanWidth_1 = width / CleanXfac_1; + CleanHeight_1 = height / CleanYfac_1; +} + //========================================================================== // // Draw parameter parsing @@ -871,3 +901,4 @@ void ScaleWithAspect(int& w, int& h, int Width, int Height) h = static_cast(y); } + diff --git a/source/common/2d/v_draw.h b/source/common/2d/v_draw.h index 3a8bfe67a..a120c0cfe 100644 --- a/source/common/2d/v_draw.h +++ b/source/common/2d/v_draw.h @@ -42,11 +42,13 @@ double AspectPspriteOffset(float aspect); int AspectMultiplier(float aspect); bool AspectTallerThanWide(float aspect); void ScaleWithAspect(int& w, int& h, int Width, int Height); +void V_UpdateModeSize(int width, int height); void DrawTexture(F2DDrawer *drawer, FTexture* img, double x, double y, int tags_first, ...); void DrawChar (F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...); void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...); void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char32_t *string, int tag_first, ...); +void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, int height, int thickness); EXTERN_CVAR(Int, con_scaletext) // Scale notify text at high resolutions? EXTERN_CVAR(Int, con_scale) diff --git a/source/common/2d/v_drawtext.cpp b/source/common/2d/v_drawtext.cpp index 7baeb213d..9bf96be39 100644 --- a/source/common/2d/v_drawtext.cpp +++ b/source/common/2d/v_drawtext.cpp @@ -44,6 +44,7 @@ #include "v_draw.h" #include "image.h" #include "v_2ddrawer.h" +#include "gstrings.h" #include "v_font.h" class FFont; @@ -225,7 +226,7 @@ void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double { return; } - DrawTextCommon(drawer, font, normalcolor, x, y, (const uint8_t*)string, parms); + DrawTextCommon(drawer, font, normalcolor, x, y, (const uint8_t*)GStrings.localize(string), parms); } void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char32_t *string, int tag_first, ...) @@ -246,3 +247,25 @@ void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double DrawTextCommon(drawer, font, normalcolor, x, y, string, parms); } +//========================================================================== +// +// V_DrawFrame +// +// Draw a frame around the specified area using the view border +// frame graphics. The border is drawn outside the area, not in it. +// +//========================================================================== + +void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, int height, int thickness) +{ + // Sanity check for incomplete gameinfo + int offset = thickness == -1 ? screen->GetHeight() / 400 : thickness; + int right = left + width; + int bottom = top + height; + + // Draw top and bottom sides. + twod->AddColorOnlyQuad(left, top - offset, width, offset, color); + twod->AddColorOnlyQuad(left - offset, top - offset, offset, height + 2 * offset, color); + twod->AddColorOnlyQuad(left, bottom, width, offset, color); + twod->AddColorOnlyQuad(right, top - offset, offset, height + 2 * offset, color); +} diff --git a/source/common/console/c_bind.cpp b/source/common/console/c_bind.cpp index b504bb41e..cfa0b9f4f 100644 --- a/source/common/console/c_bind.cpp +++ b/source/common/console/c_bind.cpp @@ -649,7 +649,7 @@ CCMD(rebind) // //============================================================================= -void ReadBindings(int lump) +void ReadBindings(int lump, bool override) { FScanner sc(lump); @@ -675,20 +675,26 @@ void ReadBindings(int lump) } key = GetConfigKeyFromName(sc.String); sc.MustGetString(); - dest->SetBind(key, sc.String); + dest->SetBind(key, sc.String, override); } } void CONFIG_SetDefaultKeys(const char* baseconfig) { - auto lump = fileSystem.GetFile(baseconfig); - ReadBindings(lump); + auto lump = fileSystem.GetFile("demolition/commonbinds.txt", ELookupMode::FullName, 0); + if (lump >= 0) ReadBindings(lump, true); int lastlump = 0; + while ((lump = fileSystem.Iterate(baseconfig, &lastlump)) != -1) + { + if (fileSystem.GetFileContainer(lump) > 0) break; + ReadBindings(lump, true); + } + while ((lump = fileSystem.Iterate("defbinds.txt", &lastlump)) != -1) { - ReadBindings(lump); + ReadBindings(lump, false); } } @@ -802,3 +808,4 @@ bool C_DoKey (event_t *ev, FKeyBindings *binds, FKeyBindings *doublebinds) } return false; } + diff --git a/source/common/console/c_bind.h b/source/common/console/c_bind.h index 9fbd32f41..babfcd5c5 100644 --- a/source/common/console/c_bind.h +++ b/source/common/console/c_bind.h @@ -61,8 +61,9 @@ public: void DoBind (const char *key, const char *bind); void DefaultBind(const char *keyname, const char *cmd); - void SetBind(unsigned int key, const char *bind) + void SetBind(unsigned int key, const char *bind, bool override = true) { + if (!override && Binds[key].IsNotEmpty()) return; if (key < NUM_KEYS) Binds[key] = bind; } @@ -115,4 +116,13 @@ struct FKeySection }; extern TArray KeySections; +struct GameFuncDesc +{ + const char *action; + const char *description; + bool replaced; +}; #endif //__C_BINDINGS_H__ + + + diff --git a/source/common/console/c_buttons.cpp b/source/common/console/c_buttons.cpp index 0d9cbb2c7..0e9939561 100644 --- a/source/common/console/c_buttons.cpp +++ b/source/common/console/c_buttons.cpp @@ -48,170 +48,72 @@ struct ButtonDesc }; static const ButtonDesc gamefuncs[] = { - { gamefunc_Move_Forward, "Move_Forward"}, - { gamefunc_Move_Backward, "Move_Backward"}, - { gamefunc_Turn_Left, "Turn_Left"}, - { gamefunc_Turn_Right, "Turn_Right"}, - { gamefunc_Strafe, "Strafe"}, - { gamefunc_Fire, "Fire"}, - { gamefunc_Open, "Open"}, - { gamefunc_Run, "Run"}, - { gamefunc_Alt_Fire, "Alt_Fire"}, - { gamefunc_Jump, "Jump"}, - { gamefunc_Crouch, "Crouch"}, - { gamefunc_Look_Up, "Look_Up"}, - { gamefunc_Look_Down, "Look_Down"}, - { gamefunc_Look_Left, "Look_Left"}, - { gamefunc_Look_Right, "Look_Right"}, - { gamefunc_Strafe_Left, "Strafe_Left"}, - { gamefunc_Strafe_Right, "Strafe_Right"}, - { gamefunc_Aim_Up, "Aim_Up"}, - { gamefunc_Aim_Down, "Aim_Down"}, - { gamefunc_Weapon_1, "Weapon_1"}, - { gamefunc_Weapon_2, "Weapon_2"}, - { gamefunc_Weapon_3, "Weapon_3"}, - { gamefunc_Weapon_4, "Weapon_4"}, - { gamefunc_Weapon_5, "Weapon_5"}, - { gamefunc_Weapon_6, "Weapon_6"}, - { gamefunc_Weapon_7, "Weapon_7"}, - { gamefunc_Weapon_8, "Weapon_8"}, - { gamefunc_Weapon_9, "Weapon_9"}, - { gamefunc_Weapon_10, "Weapon_10"}, - { gamefunc_Inventory, "Inventory"}, - { gamefunc_Inventory_Left, "Inventory_Left"}, - { gamefunc_Inventory_Right, "Inventory_Right"}, - { gamefunc_Holo_Duke, "Holo_Duke"}, - { gamefunc_Jetpack, "Jetpack"}, - { gamefunc_NightVision, "NightVision"}, - { gamefunc_MedKit, "MedKit"}, - { gamefunc_TurnAround, "Turn_Around"}, - { gamefunc_SendMessage, "Send_Message"}, - { gamefunc_Map, "Map"}, - { gamefunc_Shrink_Screen, "Shrink_Screen"}, - { gamefunc_Enlarge_Screen, "Enlarge_Screen"}, - { gamefunc_Center_View, "Center_View"}, - { gamefunc_Holster_Weapon, "Holster_Weapon"}, + { gamefunc_Move_Forward, "Move_Forward"}, + { gamefunc_Move_Backward, "Move_Backward"}, + { gamefunc_Turn_Left, "Turn_Left"}, + { gamefunc_Turn_Right, "Turn_Right"}, + { gamefunc_Strafe, "Strafe"}, + { gamefunc_Fire, "Fire"}, + { gamefunc_Open, "Open"}, + { gamefunc_Run, "Run"}, + { gamefunc_Alt_Fire, "Alt_Fire"}, + { gamefunc_Jump, "Jump"}, + { gamefunc_Crouch, "Crouch"}, + { gamefunc_Look_Up, "Look_Up"}, + { gamefunc_Look_Down, "Look_Down"}, + { gamefunc_Look_Left, "Look_Left"}, + { gamefunc_Look_Right, "Look_Right"}, + { gamefunc_Strafe_Left, "Strafe_Left"}, + { gamefunc_Strafe_Right, "Strafe_Right"}, + { gamefunc_Aim_Up, "Aim_Up"}, + { gamefunc_Aim_Down, "Aim_Down"}, + { gamefunc_Weapon_1, "Weapon_1"}, + { gamefunc_Weapon_2, "Weapon_2"}, + { gamefunc_Weapon_3, "Weapon_3"}, + { gamefunc_Weapon_4, "Weapon_4"}, + { gamefunc_Weapon_5, "Weapon_5"}, + { gamefunc_Weapon_6, "Weapon_6"}, + { gamefunc_Weapon_7, "Weapon_7"}, + { gamefunc_Weapon_8, "Weapon_8"}, + { gamefunc_Weapon_9, "Weapon_9"}, + { gamefunc_Weapon_10, "Weapon_10"}, + { gamefunc_Inventory, "Inventory"}, + { gamefunc_Inventory_Left, "Inventory_Left"}, + { gamefunc_Inventory_Right, "Inventory_Right"}, + { gamefunc_Holo_Duke, "Holo_Duke"}, + { gamefunc_Jetpack, "Jetpack"}, + { gamefunc_NightVision, "NightVision"}, + { gamefunc_MedKit, "MedKit"}, + { gamefunc_TurnAround, "Turn_Around"}, + { gamefunc_SendMessage, "Send_Message"}, + { gamefunc_Map, "Map"}, + { gamefunc_Shrink_Screen, "Shrink_Screen"}, + { gamefunc_Enlarge_Screen, "Enlarge_Screen"}, + { gamefunc_Center_View, "Center_View"}, + { gamefunc_Holster_Weapon, "Holster_Weapon"}, { gamefunc_Show_Opponents_Weapon, "Show_Opponents_Weapon"}, - { gamefunc_Map_Follow_Mode, "Map_Follow_Mode"}, + { gamefunc_Map_Follow_Mode, "Map_Follow_Mode"}, { gamefunc_See_Coop_View, "See_Coop_View"}, - { gamefunc_Mouse_Aiming, "Mouse_Aiming"}, + { gamefunc_Mouse_Aiming, "Mouse_Aiming"}, { gamefunc_Toggle_Crosshair, "Toggle_Crosshair"}, - { gamefunc_Steroids, "Steroids"}, - { gamefunc_Quick_Kick, "Quick_Kick"}, - { gamefunc_Next_Weapon, "Next_Weapon"}, - { gamefunc_Previous_Weapon, "Previous_Weapon"}, - { gamefunc_Show_Console, "Show_Console"}, - { gamefunc_Show_DukeMatch_Scores, "Show_DukeMatch_Scores"}, + { gamefunc_Steroids, "Steroids"}, + { gamefunc_Quick_Kick, "Quick_Kick"}, + { gamefunc_Next_Weapon, "Next_Weapon"}, + { gamefunc_Previous_Weapon, "Previous_Weapon"}, + { gamefunc_Show_DukeMatch_Scores, "Show_DukeMatch_Scores"}, { gamefunc_Dpad_Select, "Dpad_Select"}, { gamefunc_Dpad_Aiming, "Dpad_Aiming"}, - { gamefunc_AutoRun, "AutoRun"}, { gamefunc_Last_Weapon, "Last_Used_Weapon"}, - { gamefunc_Quick_Save, "Quick_Save"}, - { gamefunc_Quick_Load, "Quick_Load"}, - { gamefunc_Alt_Weapon, "Alt_Weapon"}, - { gamefunc_Third_Person_View, "Third_Person_View"}, - { gamefunc_Toggle_Crouch, "Toggle_Crouch"}, - { gamefunc_See_Chase_View, "See_Chase_View"}, // the following were added by Blood - { gamefunc_BeastVision, "BeastVision"}, - { gamefunc_CrystalBall, "CrystalBall"}, - { gamefunc_JumpBoots, "JumpBoots"}, - { gamefunc_ProximityBombs, "ProximityBombs"}, - { gamefunc_RemoteBombs, "RemoteBombs"}, - { gamefunc_Smoke_Bomb, "Smoke_Bomb" }, - { gamefunc_Gas_Bomb, "Gas_Bomb" }, - { gamefunc_Flash_Bomb, "Flash_Bomb" }, - { gamefunc_Caltrops, "Calitrops" }, - -}; - -static const ButtonDesc gamealiases_Duke3D[] = { - { gamefunc_BeastVision, ""}, - { gamefunc_CrystalBall, ""}, - { gamefunc_ProximityBombs, ""}, - { gamefunc_RemoteBombs, ""}, - { gamefunc_Smoke_Bomb, "" }, - { gamefunc_Gas_Bomb, "" }, - { gamefunc_Flash_Bomb, "" }, - { gamefunc_Caltrops, "" }, - -}; - -static const ButtonDesc gamealiases_Nam[] = { - { gamefunc_Holo_Duke, "Holo_Soldier"}, - { gamefunc_Jetpack, "Huey"}, - { gamefunc_Steroids, "Tank_Mode"}, - { gamefunc_Show_DukeMatch_Scores, "Show_GruntMatch_Scores"}, - { gamefunc_BeastVision, ""}, - { gamefunc_CrystalBall, ""}, - { gamefunc_ProximityBombs, ""}, - { gamefunc_RemoteBombs, ""}, - { gamefunc_Smoke_Bomb, "" }, - { gamefunc_Gas_Bomb, "" }, - { gamefunc_Flash_Bomb, "" }, - { gamefunc_Caltrops, "" }, - -}; - -static const ButtonDesc gamealiases_WW2GI[] = { - { gamefunc_Holo_Duke, "Fire Mission"}, - { gamefunc_Jetpack, ""}, - { gamefunc_Steroids, "Smokes"}, - { gamefunc_Show_DukeMatch_Scores, "Show_GIMatch_Scores"}, - { gamefunc_BeastVision, ""}, - { gamefunc_CrystalBall, ""}, - { gamefunc_ProximityBombs, ""}, - { gamefunc_RemoteBombs, ""}, - { gamefunc_Smoke_Bomb, "" }, - { gamefunc_Gas_Bomb, "" }, - { gamefunc_Flash_Bomb, "" }, - { gamefunc_Caltrops, "" }, -}; - -static const ButtonDesc gamealiases_RR[] = { - { gamefunc_Holo_Duke, "Beer"}, - { gamefunc_Jetpack, "Cow Pie"}, - { gamefunc_NightVision, "Yeehaa"}, - { gamefunc_MedKit, "Whiskey"}, - { gamefunc_Steroids, "Moonshine"}, - { gamefunc_Quick_Kick, "Pee"}, - { gamefunc_Show_DukeMatch_Scores, "Show_Scores"}, - { gamefunc_Alt_Fire, ""}, - { gamefunc_BeastVision, ""}, - { gamefunc_CrystalBall, ""}, - { gamefunc_ProximityBombs, ""}, - { gamefunc_RemoteBombs, ""}, - { gamefunc_Smoke_Bomb, "" }, - { gamefunc_Gas_Bomb, "" }, - { gamefunc_Flash_Bomb, "" }, - { gamefunc_Caltrops, "" }, -}; - -static const ButtonDesc gamealiases_Blood[] = { - { gamefunc_Holo_Duke, ""}, - { gamefunc_JumpBoots, "JumpBoots"}, - { gamefunc_Steroids, ""}, - { gamefunc_Quick_Kick, ""}, - { gamefunc_Show_DukeMatch_Scores, ""}, - { gamefunc_Alt_Weapon, ""}, - { gamefunc_Smoke_Bomb, "" }, - { gamefunc_Gas_Bomb, "" }, - { gamefunc_Flash_Bomb, "" }, - { gamefunc_Caltrops, "" }, - -}; - -static const ButtonDesc gamealiases_SW[] = { - { gamefunc_Holo_Duke, ""}, - { gamefunc_Jetpack, ""}, - { gamefunc_NightVision, ""}, - { gamefunc_MedKit, ""}, - { gamefunc_Steroids, ""}, - { gamefunc_Quick_Kick, ""}, - { gamefunc_Show_DukeMatch_Scores, ""}, - { gamefunc_Smoke_Bomb, "" }, - { gamefunc_Gas_Bomb, "" }, - { gamefunc_Flash_Bomb, "" }, - { gamefunc_Caltrops, "" }, + { gamefunc_Alt_Weapon, "Alt_Weapon"}, + { gamefunc_Third_Person_View, "Third_Person_View"}, + { gamefunc_Toggle_Crouch, "Toggle_Crouch"}, + { gamefunc_CrystalBall, "CrystalBall"}, // the following were added by Blood + { gamefunc_ProximityBombs, "ProximityBombs"}, + { gamefunc_RemoteBombs, "RemoteBombs"}, + { gamefunc_Smoke_Bomb, "Smoke_Bomb" }, + { gamefunc_Gas_Bomb, "Gas_Bomb" }, + { gamefunc_Flash_Bomb, "Flash_Bomb" }, + { gamefunc_Caltrops, "Caltrops" }, }; @@ -236,60 +138,7 @@ ButtonMap::ButtonMap() for(auto &gf : gamefuncs) { NameToNum.Insert(gf.name, gf.index); - NumToAlias[gf.index] = NumToName[gf.index] = gf.name; - } -} - -//============================================================================= -// -// -// -//============================================================================= - -void ButtonMap::SetGameAliases() -{ - // Ion Fury hacks this together from the CON script and uses the same table as Duke Nukem - if (g_gameType & (GAMEFLAG_DUKE|GAMEFLAG_FURY)) - { - for (auto& gf : gamealiases_Duke3D) - { - NumToAlias[gf.index] = gf.name; - } - } - if (g_gameType & GAMEFLAG_NAM) - { - for (auto& gf : gamealiases_Nam) - { - NumToAlias[gf.index] = gf.name; - } - } - if (g_gameType & GAMEFLAG_WW2GI) - { - for (auto& gf : gamealiases_WW2GI) - { - NumToAlias[gf.index] = gf.name; - } - } - if (g_gameType & (GAMEFLAG_RR|GAMEFLAG_RRRA)) - { - for (auto& gf : gamealiases_RR) - { - NumToAlias[gf.index] = gf.name; - } - } - if (g_gameType & GAMEFLAG_BLOOD) - { - for (auto& gf : gamealiases_Blood) - { - NumToAlias[gf.index] = gf.name; - } - } - if (g_gameType & GAMEFLAG_SW) - { - for (auto& gf : gamealiases_SW) - { - NumToAlias[gf.index] = gf.name; - } + NumToName[gf.index] = gf.name; } } @@ -306,18 +155,16 @@ int ButtonMap::ListActionCommands (const char *pattern) for (int i = 0; i < NumButtons(); i++) { - if (NumToAlias[i].IsEmpty()) continue; // do not list buttons that were removed from the alias list - if (pattern == NULL || CheckWildcards (pattern, (snprintf (matcher, countof(matcher), "+%s", NumToName[i].GetChars()), matcher))) { - Printf ("+%s\n", NumToName[i]); + Printf ("+%s\n", NumToName[i].GetChars()); count++; } if (pattern == NULL || CheckWildcards (pattern, (snprintf (matcher, countof(matcher), "-%s", NumToName[i].GetChars()), matcher))) { - Printf ("-%s\n", NumToName[i]); + Printf ("-%s\n", NumToName[i].GetChars()); count++; } } @@ -374,34 +221,6 @@ void ButtonMap::ResetButtonStates () } } -//============================================================================= -// -// -// -//============================================================================= - -void ButtonMap::SetButtonAlias(int num, const char *text) -{ - if ((unsigned)num >= (unsigned)NUMGAMEFUNCTIONS) - return; - NumToAlias[num] = text; - NameToNum.Insert(text, num); -} - -//============================================================================= -// -// -// -//============================================================================= - -void ButtonMap::ClearButtonAlias(int num) -{ - if ((unsigned)num >= (unsigned)NUMGAMEFUNCTIONS) - return; - NumToAlias[num] = ""; -} - - //============================================================================= // // @@ -497,4 +316,3 @@ bool FButtonStatus::ReleaseKey (int keynum) // Returns true if releasing this key caused the button to go up. return wasdown && !bDown; } - diff --git a/source/common/console/c_buttons.h b/source/common/console/c_buttons.h index 2efac99af..7a3cd2773 100644 --- a/source/common/console/c_buttons.h +++ b/source/common/console/c_buttons.h @@ -46,6 +46,7 @@ enum GameFunction_t gamefunc_JumpBoots = gamefunc_Jetpack, gamefunc_NightVision, gamefunc_Night_Vision = gamefunc_NightVision, + gamefunc_BeastVision = gamefunc_NightVision, gamefunc_MedKit, gamefunc_Med_Kit = gamefunc_MedKit, gamefunc_TurnAround, @@ -68,19 +69,14 @@ enum GameFunction_t gamefunc_Quick_Kick, gamefunc_Next_Weapon, gamefunc_Previous_Weapon, - gamefunc_Show_Console, gamefunc_Show_DukeMatch_Scores, gamefunc_Dpad_Select, gamefunc_Dpad_Aiming, - gamefunc_AutoRun, gamefunc_Last_Weapon, - gamefunc_Quick_Save, - gamefunc_Quick_Load, gamefunc_Alt_Weapon, gamefunc_Third_Person_View, - gamefunc_See_Chase_View = gamefunc_Third_Person_View, // this was added by Blood - gamefunc_Toggle_Crouch, - gamefunc_BeastVision, + gamefunc_See_Chase_View = gamefunc_Third_Person_View, + gamefunc_Toggle_Crouch, // This is the last one used by EDuke32. gamefunc_CrystalBall, gamefunc_ProximityBombs, gamefunc_RemoteBombs, @@ -119,7 +115,6 @@ class ButtonMap FButtonStatus Buttons[NUMGAMEFUNCTIONS]; FString NumToName[NUMGAMEFUNCTIONS]; // The internal name of the button - FString NumToAlias[NUMGAMEFUNCTIONS]; // The display name which can be altered by scripts. TMap NameToNum; public: @@ -139,6 +134,7 @@ public: return index > -1? &Buttons[index] : nullptr; } + // This is still in use but all cases are scheduled for termination. const char* GetButtonName(int32_t func) const { if ((unsigned)func >= (unsigned)NumButtons()) @@ -146,15 +142,6 @@ public: return NumToName[func]; } - const char* GetButtonAlias(int32_t func) const - { - if ((unsigned)func >= (unsigned)NumButtons()) - return nullptr; - return NumToAlias[func]; - } - - void SetButtonAlias(int num, const char* text); - void ClearButtonAlias(int num); void ResetButtonTriggers (); // Call ResetTriggers for all buttons void ResetButtonStates (); // Same as above, but also clear bDown int ListActionCommands(const char* pattern); diff --git a/source/common/console/c_con.cpp b/source/common/console/c_con.cpp new file mode 100644 index 000000000..df40bde31 --- /dev/null +++ b/source/common/console/c_con.cpp @@ -0,0 +1,276 @@ +/* +** c_con.cpp +** Interface for CON scripts. +** +** +**--------------------------------------------------------------------------- +** Copyright 2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include "basics.h" +#include "zstring.h" +#include "c_bind.h" +#include "control.h" +#include "gamecontrol.h" + +//============================================================================= +// +// Interface for CON scripts to get descriptions for actions +// This code can query the 64 original game functions by index. +// +// This is mostly an ill-advised hackery to change menu texts. It no longer +// changes the menu but gets used when scripts try to write +// key related messages. Ion Fury uses this and is one of the reasons +// why that game is by all accounts not localizable. +// +// Important note: The list of actions may not be altered. If some of these +// commands get refactored, the string below needs to be changed to match +// the new command. +// +//============================================================================= + +static GameFuncDesc con_gamefuncs[] = { +{"+Move_Forward", "Move_Forward"}, +{"+Move_Backward", "Move_Backward"}, +{"+Turn_Left", "Turn_Left"}, +{"+Turn_Right", "Turn_Right"}, +{"+Strafe", "Strafe"}, +{"+Fire", "Fire"}, +{"+Open", "Open"}, +{"+Run", "Run"}, +{"+Alt_Fire", "Alt_Fire"}, +{"+Jump", "Jump"}, +{"+Crouch", "Crouch"}, +{"+Look_Up", "Look_Up"}, +{"+Look_Down", "Look_Down"}, +{"+Look_Left", "Look_Left"}, +{"+Look_Right", "Look_Right"}, +{"+Strafe_Left", "Strafe_Left"}, +{"+Strafe_Right", "Strafe_Right"}, +{"+Aim_Up", "Aim_Up"}, +{"+Aim_Down", "Aim_Down"}, +{"+Weapon_1", "Weapon_1"}, +{"+Weapon_2", "Weapon_2"}, +{"+Weapon_3", "Weapon_3"}, +{"+Weapon_4", "Weapon_4"}, +{"+Weapon_5", "Weapon_5"}, +{"+Weapon_6", "Weapon_6"}, +{"+Weapon_7", "Weapon_7"}, +{"+Weapon_8", "Weapon_8"}, +{"+Weapon_9", "Weapon_9"}, +{"+Weapon_10", "Weapon_10"}, +{"+Inventory", "Inventory"}, +{"+Inventory_Left", "Inventory_Left"}, +{"+Inventory_Right", "Inventory_Right"}, +{"+Holo_Duke", "Holo_Duke"}, +{"+Jetpack", "Jetpack"}, +{"+NightVision", "NightVision"}, +{"+MedKit", "MedKit"}, +{"+TurnAround", "TurnAround"}, +{"+SendMessage", "SendMessage"}, +{"+Map", "Map"}, +{"+Shrink_Screen", "Shrink_Screen"}, +{"+Enlarge_Screen", "Enlarge_Screen"}, +{"+Center_View", "Center_View"}, +{"+Holster_Weapon", "Holster_Weapon"}, +{"+Show_Opponents_Weapon", "Show_Opponents_Weapon"}, +{"+Map_Follow_Mode", "Map_Follow_Mode"}, +{"+See_Coop_View", "See_Coop_View"}, +{"+Mouse_Aiming", "Mouse_Aiming"}, +{"+Toggle_Crosshair", "Toggle_Crosshair"}, +{"+Steroids", "Steroids"}, +{"+Quick_Kick", "Quick_Kick"}, +{"+Next_Weapon", "Next_Weapon"}, +{"+Previous_Weapon", "Previous_Weapon"}, +{"ToggleConsole", "Show_Console"}, +{"+Show_DukeMatch_Scores", "Show_Scoreboard"}, +{"+Dpad_Select", "Dpad_Select"}, +{"+Dpad_Aiming", "Dpad_Aiming"}, +{"toggle cl_autorun", "AutoRun"}, +{"+Last_Used_Weapon", "Last_Used_Weapon"}, +{"QuickSave", "Quick_Save"}, +{"QuickLoad", "Quick_Load"}, +{"+Alt_Weapon", "Alt_Weapon"}, +{"+Third_Person_View", "Third_Person_View"}, +{"+Toggle_Crouch", "Toggle_Crouch"} +}; + +//============================================================================= +// +// +// +//============================================================================= + +void C_CON_SetAliases() +{ + if (g_gameType & GAMEFLAG_NAM) + { + con_gamefuncs[32].description = "Holo_Soldier"; + con_gamefuncs[33].description = "Huey"; + con_gamefuncs[48].description = "Tank_Mode"; + } + if (g_gameType & GAMEFLAG_WW2GI) + { + con_gamefuncs[32].description = "Fire_Mission"; + con_gamefuncs[33].description = ""; + con_gamefuncs[48].description = "Smokes"; + } + +} + +static FString C_CON_GetGameFuncOnKeyboard(int gameFunc) +{ + if (gameFunc >= 0 && gameFunc < countof(con_gamefuncs)) + { + auto keys = Bindings.GetKeysForCommand(con_gamefuncs[gameFunc].action); + for (auto key : keys) + { + if (key < KEY_FIRSTMOUSEBUTTON) + { + auto scan = KB_ScanCodeToString(key); + if (scan) return scan; + } + } + } + return ""; +} + +static FString C_CON_GetGameFuncOnMouse(int gameFunc) +{ + if (gameFunc >= 0 && gameFunc < countof(con_gamefuncs)) + { + auto keys = Bindings.GetKeysForCommand(con_gamefuncs[gameFunc].action); + for (auto key : keys) + { + if ((key >= KEY_FIRSTMOUSEBUTTON && key < KEY_FIRSTJOYBUTTON) || (key >= KEY_MWHEELUP && key <= KEY_MWHEELLEFT)) + { + auto scan = KB_ScanCodeToString(key); + if (scan) return scan; + } + } + } + return ""; +} + +char const* C_CON_GetGameFuncOnJoystick(int gameFunc) +{ + if (gameFunc >= 0 && gameFunc < countof(con_gamefuncs)) + { + auto keys = Bindings.GetKeysForCommand(con_gamefuncs[gameFunc].action); + for (auto key : keys) + { + if (key >= KEY_FIRSTJOYBUTTON && !(key >= KEY_MWHEELUP && key <= KEY_MWHEELLEFT)) + { + auto scan = KB_ScanCodeToString(key); + if (scan) return scan; + } + } + } + return ""; +} + +FString C_CON_GetBoundKeyForLastInput(int gameFunc) +{ + if (CONTROL_LastSeenInput == LastSeenInput::Joystick) + { + FString name = C_CON_GetGameFuncOnJoystick(gameFunc); + if (name.IsNotEmpty()) + { + return name; + } + } + + FString name = C_CON_GetGameFuncOnKeyboard(gameFunc); + if (name.IsNotEmpty()) + { + return name; + } + + name = C_CON_GetGameFuncOnMouse(gameFunc); + if (name.IsNotEmpty()) + { + return name; + } + + name = C_CON_GetGameFuncOnJoystick(gameFunc); + if (name.IsNotEmpty()) + { + return name; + } + return "UNBOUND"; +} + + +//============================================================================= +// +// +// +//============================================================================= + +void C_CON_SetButtonAlias(int num, const char *text) +{ + if (num >= 0 && num < countof(con_gamefuncs)) + { + if (con_gamefuncs[num].replaced) free((void*)con_gamefuncs[num].description); + con_gamefuncs[num].description = strdup(text); + con_gamefuncs[num].replaced = true; + } +} + +//============================================================================= +// +// +// +//============================================================================= + +void C_CON_ClearButtonAlias(int num) +{ + if (num >= 0 && num < countof(con_gamefuncs)) + { + if (con_gamefuncs[num].replaced) free((void*)con_gamefuncs[num].description); + con_gamefuncs[num].description = ""; + con_gamefuncs[num].replaced = false; + } +} + +//============================================================================= +// +// +// +//============================================================================= + +const char *C_CON_GetButtonFunc(int num) +{ + if (num >= 0 && num < countof(con_gamefuncs)) + { + return con_gamefuncs[num].action; + } + return ""; +} diff --git a/source/common/console/c_console.cpp b/source/common/console/c_console.cpp index 0a029990a..aaeff2b06 100644 --- a/source/common/console/c_console.cpp +++ b/source/common/console/c_console.cpp @@ -53,6 +53,9 @@ #include "v_font.h" #include "printf.h" #include "inputstate.h" +#include "i_time.h" +#include "gamecvars.h" +#include "baselayer.h" #define LEFTMARGIN 8 @@ -123,15 +126,13 @@ static GameAtExit *ExitCmdList; #define SCROLLDN 2 #define SCROLLNO 0 -CVAR (Bool, show_messages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) - // Buffer for AddToConsole() static char *work = NULL; static int worklen = 0; CVAR(Float, con_notifytime, 3.f, CVAR_ARCHIVE) CVAR(Bool, con_centernotify, false, CVAR_ARCHIVE) -CUSTOM_CVAR(Int, con_scaletext, 0, CVAR_ARCHIVE) // Scale notify text at high resolutions? +CUSTOM_CVAR(Int, con_scaletext, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // Scale notify text at high resolutions? { if (self < 0) self = 0; } @@ -205,13 +206,13 @@ public: if (scale == 1) { DrawChar(&twod, CurrentConsoleFont, CR_ORANGE, x, y, '\x1c', TAG_DONE); - DrawText(&twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y, + DrawText(&twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->CharWidth(0x1c), y, &Text[StartPos], TAG_DONE); if (cursor) { DrawChar(&twod, CurrentConsoleFont, CR_YELLOW, - x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb), + x + CurrentConsoleFont->CharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->CharWidth(0xb), y, '\xb', TAG_DONE); } } @@ -222,7 +223,7 @@ public: DTA_VirtualHeight, screen->GetHeight() / scale, DTA_KeepRatio, true, TAG_DONE); - DrawText(&twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y, + DrawText(&twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->CharWidth(0x1c), y, &Text[StartPos], DTA_VirtualWidth, screen->GetWidth() / scale, DTA_VirtualHeight, screen->GetHeight() / scale, @@ -231,7 +232,7 @@ public: if (cursor) { DrawChar(&twod, CurrentConsoleFont, CR_YELLOW, - x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb), + x + CurrentConsoleFont->CharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->CharWidth(0xb), y, '\xb', DTA_VirtualWidth, screen->GetWidth() / scale, DTA_VirtualHeight, screen->GetHeight() / scale, @@ -541,7 +542,7 @@ CUSTOM_CVAR(Int, con_notifylines, NUMNOTIFIES, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) } -int PrintColors[PRINTLEVELS+2] = { CR_RED, CR_GOLD, CR_GRAY, CR_GREEN, CR_GREEN, CR_GOLD }; +int PrintColors[PRINTLEVELS+2] = { CR_RED, CR_GOLD, CR_YELLOW, CR_GREEN, CR_GREEN, CR_GOLD }; static void setmsgcolor (int index, int color); @@ -614,7 +615,7 @@ void C_InitConsole (int width, int height, bool ingame) vidactive = ingame; if (CurrentConsoleFont != NULL) { - cwidth = CurrentConsoleFont->GetCharWidth ('M'); + cwidth = CurrentConsoleFont->CharWidth ('M'); cheight = CurrentConsoleFont->GetHeight(); } else @@ -775,7 +776,7 @@ void FNotifyBuffer::AddString(int printlevel, FString source) TArray lines; int width; - if ((printlevel != 128 && !show_messages) || + if (hud_messages != 2 || source.IsEmpty() || //gamestate == GS_FULLCONSOLE || //gamestate == GS_DEMOSCREEN || @@ -901,7 +902,7 @@ int PrintString (int iprintlevel, const char *outline) #endif conbuffer->AddText(printlevel, outline); - if (vidactive && screen && !(iprintlevel & PRINT_NONOTIFY)) + if (vidactive && (iprintlevel & PRINT_NOTIFY)) { NotifyStrings.AddString(printlevel, outline); } @@ -959,7 +960,7 @@ void OSD_Printf(const char *format, ...) int count; va_start (argptr, format); - count = VPrintf (PRINT_HIGH|PRINT_NONOTIFY, format, argptr); + count = VPrintf (PRINT_HIGH, format, argptr); va_end (argptr); } @@ -1074,7 +1075,7 @@ void FNotifyBuffer::Tick() if (Text[i].TimeOut != 0 && --Text[i].TimeOut <= 0) break; } - if (i > 0) + if (i < Text.Size()) { Text.Delete(0, i); } @@ -1106,9 +1107,6 @@ void FNotifyBuffer::Draw() j = notify.TimeOut; if (j > 0) { - if (!show_messages && notify.PrintLevel != 128) - continue; - double alpha = (j < NOTIFYFADETIME) ? 1. * j / NOTIFYFADETIME : 1; if (notify.PrintLevel >= PRINTLEVELS) @@ -1320,13 +1318,14 @@ void C_ToggleConsole () HistPos = NULL; TabbedLast = false; TabbedList = false; - GUICapture |= 1; + mouseGrabInput(false); + } else //if (gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) { ConsoleState = c_rising; C_FlushDisplay (); - GUICapture &= ~1; + mouseGrabInput(true); } } @@ -1802,7 +1801,7 @@ void C_MidPrint (FFont *font, const char *msg, bool bold) if (msg != nullptr) { auto color = (EColorRange)PrintColors[bold? PRINTLEVELS+1 : PRINTLEVELS]; - Printf(PRINT_HIGH|PRINT_NONOTIFY, TEXTCOLOR_ESCAPESTR "%c%s\n%s\n%s\n", color, console_bar, msg, console_bar); + Printf(PRINT_HIGH, TEXTCOLOR_ESCAPESTR "%c%s\n%s\n%s\n", color, console_bar, msg, console_bar); StatusBar->AttachMessage (Create(font, msg, 1.5f, 0.375f, 0, 0, color, con_midtime), MAKE_ID('C','N','T','R')); } diff --git a/source/common/console/c_cvars.cpp b/source/common/console/c_cvars.cpp index 23b5d7afa..195bfe51a 100644 --- a/source/common/console/c_cvars.cpp +++ b/source/common/console/c_cvars.cpp @@ -38,12 +38,14 @@ #include "c_cvars.h" #include "configfile.h" +#include "baselayer.h" #include "c_console.h" #include "gamecvars.h" #include "cmdlib.h" #include "c_dispatch.h" #include "printf.h" +#include "quotemgr.h" struct FLatchedValue @@ -142,7 +144,7 @@ FBaseCVar::~FBaseCVar () const char *FBaseCVar::GetHumanString(int precision) const { assert(true); - return "";// GetGenericRep(CVAR_String).String; + return GetGenericRep(CVAR_String).String; } void FBaseCVar::ForceSet (UCVarValue value, ECVarType type, bool nouserinfosend) @@ -1511,8 +1513,23 @@ CCMD (toggle) val = var->GetGenericRep (CVAR_Bool); val.Bool = !val.Bool; var->SetGenericRep (val, CVAR_Bool); - Printf ("\"%s\" = \"%s\"\n", var->GetName(), - val.Bool ? "true" : "false"); + const char *statestr = argv.argc() <= 2? "*" : argv[2]; + if (*statestr == '*') + { + gi->PrintMessage(PRINT_MEDIUM, "\"%s\" = \"%s\"\n", var->GetName(), val.Bool ? "true" : "false"); + } + else + { + int state = (int)strtoll(argv[2], nullptr, 0); + if (state != 0) + { + // Order of Duke's quote string varies, some have on first, some off, so use the sign of the parameter to decide. + // Positive means Off/On, negative means On/Off + int quote = state > 0? state + val.Bool : -(state + val.Bool); + auto text = quoteMgr.GetQuote(quote); + if (text) gi->PrintMessage(PRINT_MEDIUM, "%s\n", text); + } + } } } } diff --git a/source/common/console/d_event.cpp b/source/common/console/d_event.cpp index 3846e5829..03b424c8e 100644 --- a/source/common/console/d_event.cpp +++ b/source/common/console/d_event.cpp @@ -1,30 +1,44 @@ -//----------------------------------------------------------------------------- -// -// Copyright 1993-1996 id Software -// Copyright 1999-2016 Randy Heit -// Copyright 2002-2016 Christoph Oelckers -// -// 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 -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -// -//----------------------------------------------------------------------------- +/* +** c_dispatch.cpp +** Functions for executing console commands and aliases +** +**--------------------------------------------------------------------------- +** Copyright 1998-2016 Randy Heit +** Copyright 2003-2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ #include "c_bind.h" #include "d_event.h" #include "c_console.h" #include "d_gui.h" #include "inputstate.h" +#include "menu.h" int eventhead; int eventtail; @@ -39,62 +53,6 @@ event_t events[NUM_EVENTS]; bool G_Responder (event_t *ev) { -#if 0 - // any other key pops up menu if in demos - // [RH] But only if the key isn't bound to a "special" command - if (gameaction == ga_nothing && - (demoplayback || gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL)) - { - const char *cmd = Bindings.GetBind (ev->data1); - - if (ev->type == EV_KeyDown) - { - - if (!cmd || ( - strnicmp (cmd, "menu_", 5) && - stricmp (cmd, "toggleconsole") && - stricmp (cmd, "sizeup") && - stricmp (cmd, "sizedown") && - stricmp (cmd, "togglemap") && - stricmp (cmd, "spynext") && - stricmp (cmd, "spyprev") && - stricmp (cmd, "chase") && - stricmp (cmd, "+showscores") && - stricmp (cmd, "bumpgamma") && - stricmp (cmd, "screenshot"))) - { - M_StartControlPanel(true); - M_SetMenu(NAME_Mainmenu, -1); - return true; - } - else - { - return - C_DoKey (ev, &Bindings, &DoubleBindings); - } - } - if (cmd && cmd[0] == '+') - return C_DoKey (ev, &Bindings, &DoubleBindings); - - return false; - } -#endif - -#if 0 - if (gamestate == GS_LEVEL) - { - if (ST_Responder (ev)) - return true; // status window ate it - if (!viewactive && primaryLevel->automap->Responder (ev, false)) - return true; // automap ate it - } - else if (gamestate == GS_FINALE) - { - if (F_Responder (ev)) - return true; // finale ate the event - } -#endif - switch (ev->type) { case EV_KeyDown: @@ -115,10 +73,11 @@ bool G_Responder (event_t *ev) #endif } - // [RH] If the view is active, give the automap a chance at - // the events *last* so that any bound keys get precedence. #if 0 + // [RH] If the view is active, give the automap a chance at + // the events *last* so that any bound keys get precedence. + // An option for later. Currently the automap is insufficiently separated from the game loop if (gamestate == GS_LEVEL && viewactive && primaryLevel->automap) return primaryLevel->automap->Responder (ev, true); #endif @@ -150,10 +109,8 @@ void D_ProcessEvents (void) (void)0;//UpdateJoystickMenu(I_UpdateDeviceList()); if (C_Responder (ev)) continue; // console ate the event -#if 0 if (M_Responder (ev)) continue; // menu ate the event -#endif G_Responder (ev); } } @@ -186,13 +143,6 @@ void D_PostEvent (const event_t *ev) return; } - if ((GUICapture & 8) && ev->type == EV_KeyDown) - { - // This must bypass the entire event management - sendKeyForBinding(ev->data1); - return; - } - // Add the key to the global keyboard state. // This is probably the biggest roadblock with the input system as it undermines a proper event driven approach. // Too much code depends on just checking this instead of waiting for events to happen. diff --git a/source/common/console/d_event.h b/source/common/console/d_event.h index 53f413454..5723ca3aa 100644 --- a/source/common/console/d_event.h +++ b/source/common/console/d_event.h @@ -1,36 +1,6 @@ -//----------------------------------------------------------------------------- -// -// Copyright 1993-1996 id Software -// Copyright 1999-2016 Randy Heit -// Copyright 2002-2016 Christoph Oelckers -// -// 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 -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//----------------------------------------------------------------------------- - - -#ifndef __D_EVENT_H__ -#define __D_EVENT_H__ - - +#pragma once #include - -// -// Event handling. -// - // Input event types. enum EGenericEvent { @@ -47,7 +17,7 @@ struct event_t { uint8_t type; uint8_t subtype; - int16_t data1; // keys / mouse/joystick buttons + int16_t data1; // keys / mouse/joystick buttons int16_t data2; int16_t data3; int x; // mouse/joystick x move @@ -61,10 +31,6 @@ void D_PostEvent (const event_t* ev); void D_RemoveNextCharEvent(); void D_ProcessEvents(void); - -// -// GLOBAL VARIABLES -// enum { NUM_EVENTS = 128 @@ -72,5 +38,3 @@ enum extern event_t events[NUM_EVENTS]; - -#endif diff --git a/source/common/filesystem/file_directory.cpp b/source/common/filesystem/file_directory.cpp index bbc6d23f5..30686bf77 100644 --- a/source/common/filesystem/file_directory.cpp +++ b/source/common/filesystem/file_directory.cpp @@ -149,8 +149,10 @@ int FDirectory::AddDirectory(const char *dirpath) (fi[1] == '\0' || (fi[1] == '.' && fi[2] == '\0')))) { - // Skip if requested and do not record . and .. directories. - continue; + // Movie and music subdirectories must always pass. + if (fi.CompareNoCase("movie") && fi.CompareNoCase("music")) + // Skip if requested and do not record . and .. directories. + continue; } FString newdir = dirpath; newdir << fi << '/'; diff --git a/source/common/filesystem/filesystem.cpp b/source/common/filesystem/filesystem.cpp index 9525f6081..b7bbee4e1 100644 --- a/source/common/filesystem/filesystem.cpp +++ b/source/common/filesystem/filesystem.cpp @@ -48,6 +48,7 @@ #include "filesystem.h" #include "resourcefile.h" #include "v_text.h" +#include "c_dispatch.h" //#include "md5.h" //#include "doomstat.h" @@ -230,7 +231,8 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept { for (i = 0; i < Files.Size(); ++i) { - if (stricmp (GetResourceFileName (i), name) == 0) + auto pth = ExtractFileBase(GetResourceFileName(i), true); + if (stricmp (pth.GetChars(), name) == 0) { return i; } @@ -321,6 +323,7 @@ int FileSystem::FindResource (int resid, const char *type, int filenum) const no for (i = fli[int(resid) % NumEntries]; i != NULL_INDEX; i = nli[i]) { if (filenum > 0 && FileInfo[i].rfnum != filenum) continue; + if (FileInfo[i].lump->ResourceId != resid) continue; auto lump = FileInfo[i].lump; if (lump->LumpName[lookuptype] == lname) return i; } @@ -481,7 +484,7 @@ int FileSystem::Iterate (const char *name, int *lastlump, ELookupMode lookupmode } lump_p = &FileInfo[*lastlump]; - while (lump_p < &FileInfo[NumEntries]) + while (lump_p <= &FileInfo.Last()) { auto lump = lump_p->lump; if (lump->LumpName[lookupindex] == lname) @@ -767,6 +770,13 @@ FileReader FileSystem::ReopenFileReader(int lump, bool alwayscache) return rl->NewReader(); // This always gets a reader to the cache } +FileReader FileSystem::OpenFileReader(const char* name, int where) +{ + auto lump = FindFile(name); + if (lump < 0) return FileReader(); + else return OpenFileReader(lump); +} + //========================================================================== // // GetAllFilesOfType @@ -1063,28 +1073,18 @@ static void PrintLastError () } #endif -#if 0 -void FileSystem::HashDump() +CCMD(printfs) { - FILE* f = fopen("fs_hash.txt", "wb"); - for (int list = 0; list < 5; list++) - { - fprintf(f, "List %d\n------------\n", list); - auto fli = FirstFileIndex[list]; - auto nli = NextFileIndex[list]; - for (int hash = 0; hash < NumEntries; hash++) - { - if (fli[hash] != NULL_INDEX) - { - fprintf(f, "\tHash %d\n", hash); - for (uint32_t i = fli[hash]; i != NULL_INDEX; i = nli[i]) - { - auto lump = FileInfo[i].lump; - fprintf(f, "\t\t%s (%d)\t%d, %d\n", lump->LumpName[list].GetChars(), lump->LumpName[list].GetIndex(), lump->Size(), i); - } - } - } - } - fclose(f); + fileSystem.PrintDirectory(); +} + +void FileSystem::PrintDirectory() +{ + for (int i = 0; i < NumEntries; i++) + { + auto lump = FileInfo[i].lump; + auto f = GetFileContainer(i); + auto n = GetResourceFileFullName(f); + Printf("%5d: %9d %64s %4s %3d %s\n", i, lump->LumpSize, lump->LumpName[0].GetChars(), lump->LumpName[4].GetChars(), lump->ResourceId, n); + } } -#endif \ No newline at end of file diff --git a/source/common/filesystem/filesystem.h b/source/common/filesystem/filesystem.h index cf3b6b307..028716c44 100644 --- a/source/common/filesystem/filesystem.h +++ b/source/common/filesystem/filesystem.h @@ -95,12 +95,25 @@ public: int FindFile (const char *name, ELookupMode lookupmode = ELookupMode::FullName, int filenum = -1) const noexcept; int GetFile (const char *name, ELookupMode lookupmode = ELookupMode::FullName, int filenum = -1) const; // Like FindFile, but throws an exception when it cannot find what it looks for. + bool FileExists(const char* name) + { + return FindFile(name) >= 0; + } int FindFile (const FString &name, ELookupMode lookupmode = ELookupMode::FullName, int filenum = -1) const noexcept { return FindFile(name.GetChars(), lookupmode, filenum); } int GetFile (const FString &name, ELookupMode lookupmode = ELookupMode::FullName, int filenum = -1) const { return GetFile(name.GetChars(), lookupmode, filenum); } + bool FileExists(const FString & name) + { + return FindFile(name) >= 0; + } int FindFile (const std::string &name, ELookupMode lookupmode = ELookupMode::FullName, int filenum = -1) const noexcept { return FindFile(name.c_str(), lookupmode, filenum); } int GetFile (const std::string &name, ELookupMode lookupmode = ELookupMode::FullName, int filenum = -1) const { return GetFile(name.c_str(), lookupmode, filenum); } + bool FileExists(const std::string& name) + { + return FindFile(name) >= 0; + } + int FindResource (int resid, const char *type, int filenum = -1) const noexcept; int GetResource (int resid, const char *type, int filenum = -1) const; // Like FindFile, but throws an exception when it cannot find what it looks for. @@ -112,6 +125,15 @@ public: TArray GetFileData(int file, int pad = 0); // reads file into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!) FileData ReadFile (int file); FileData ReadFile (const char *name) { return ReadFile (GetFile (name)); } + + inline TArray LoadFile(const char* name, int padding) + { + auto lump = FindFile(name); + if (lump < 0) return TArray(); + return GetFileData(lump, padding); + } + + const void *Lock(int lump); void Unlock(int lump, bool mayfree = false); @@ -127,6 +149,7 @@ public: FileReader OpenFileReader(int file); // opens a reader that redirects to the containing file's one. FileReader ReopenFileReader(int file, bool alwayscache = false); // opens an independent reader. + FileReader OpenFileReader(const char* name, int where); int Iterate (const char *name, int *lastfile, ELookupMode lookupmode = ELookupMode::FullName); // [RH] Find files with duplication @@ -148,6 +171,7 @@ public: { return FileInfo[lump].lump; } + void PrintDirectory(); protected: diff --git a/source/common/filesystem/resourcefile.cpp b/source/common/filesystem/resourcefile.cpp index 833b72e94..446db0deb 100644 --- a/source/common/filesystem/resourcefile.cpp +++ b/source/common/filesystem/resourcefile.cpp @@ -303,15 +303,15 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize) int lastpos = -1; FString file; - if (LumpFilter.IndexOf('.') < 0) + auto segments = LumpFilter.Split("."); + FString build; + + for (auto& segment : segments) { + if (build.IsEmpty()) build = segment; + else build << "." << segment; max -= FilterLumps(LumpFilter, lumps, lumpsize, max); } - else while ((len = LumpFilter.IndexOf('.', lastpos+1)) > 0) - { - max -= FilterLumps(LumpFilter.Left(len), lumps, lumpsize, max); - lastpos = len; - } JunkLeftoverFilters(lumps, lumpsize, max); } diff --git a/source/common/fonts/font.cpp b/source/common/fonts/font.cpp index 26d62aac8..5f64a4bca 100644 --- a/source/common/fonts/font.cpp +++ b/source/common/fonts/font.cpp @@ -576,11 +576,11 @@ FTexture *FFont::GetChar (int code, int translation, int *const width, bool *red //========================================================================== // -// FFont :: GetCharWidth +// FFont :: CharWidth // //========================================================================== -int FFont::GetCharWidth (int code) const +int FFont::CharWidth (int code) const { code = GetCharCode(code, true); if (code >= 0) return Chars[code - FirstChar].XMove; @@ -684,7 +684,7 @@ int FFont::StringWidth(const uint8_t *string) const } else { - w += GetCharWidth(chr) + GlobalKerning; + w += CharWidth(chr) + GlobalKerning; } } diff --git a/source/common/fonts/fontchars.cpp b/source/common/fonts/fontchars.cpp index 3298c5212..caa5a874d 100644 --- a/source/common/fonts/fontchars.cpp +++ b/source/common/fonts/fontchars.cpp @@ -34,7 +34,7 @@ ** */ -#include "cache1d.h" +#include "filesystem/filesystem.h" #include "bitmap.h" #include "image.h" #include "imagehelpers.h" @@ -89,8 +89,8 @@ void FFontChar1::Create8BitPixels (uint8_t *data) // //========================================================================== -FFontChar2::FFontChar2 (const char *sourcelump, int sourcepos, int width, int height, int leftofs, int topofs) -: SourceLump (sourcelump), SourcePos (sourcepos), SourceRemap(nullptr) +FFontChar2::FFontChar2 (TArray& sourcelump, int sourcepos, int width, int height, int leftofs, int topofs) +: sourceData (sourcelump), SourcePos (sourcepos), SourceRemap(nullptr) { Size.x = width; Size.y = height; @@ -119,7 +119,8 @@ void FFontChar2::SetSourceRemap(const uint8_t *sourceremap) void FFontChar2::Create8BitPixels(uint8_t *Pixels) { - auto lump = kopenFileReader(SourceLump, 0); + FileReader lump; + lump.OpenMemory(sourceData.Data(), sourceData.Size()); int destSize = GetWidth() * GetHeight(); uint8_t max = 255; bool rle = true; @@ -225,7 +226,23 @@ void FFontChar2::Create8BitPixels(uint8_t *Pixels) if (destSize < 0) { - I_Error ("The font %s is corrupt", SourceLump.GetChars()); + I_Error ("The font %s is corrupt", GetName().GetChars()); } } +FBitmap FFontChar2::GetBgraBitmap(const PalEntry* remap, int* ptrans) +{ + FBitmap bmp; + TArray buffer; + bmp.Create(Size.x, Size.y); + const uint8_t* ppix = Get8BitPixels(); + if (!ppix) + { + // This is needed for tiles with a palette remap. + buffer.Resize(Size.x * Size.y); + Create8BitPixels(buffer.Data()); + ppix = buffer.Data(); + } + if (ppix) bmp.CopyPixelData(0, 0, ppix, Size.x, Size.y, Size.y, 1, 0, remap); + return bmp; +} diff --git a/source/common/fonts/fontchars.h b/source/common/fonts/fontchars.h index 6cd240e77..42f1f9c9f 100644 --- a/source/common/fonts/fontchars.h +++ b/source/common/fonts/fontchars.h @@ -20,13 +20,14 @@ protected: class FFontChar2 : public FTexture { public: - FFontChar2 (const char *sourcelump, int sourcepos, int width, int height, int leftofs=0, int topofs=0); + FFontChar2 (TArray& sourceData, int sourcepos, int width, int height, int leftofs=0, int topofs=0); void Create8BitPixels(uint8_t*) override; + FBitmap GetBgraBitmap(const PalEntry* remap, int* ptrans) override; void SetSourceRemap(const uint8_t *sourceremap); protected: - FString SourceLump; + TArray& sourceData; int SourcePos; const uint8_t *SourceRemap; }; diff --git a/source/common/fonts/singlelumpfont.cpp b/source/common/fonts/singlelumpfont.cpp index dac6aef83..47282ac97 100644 --- a/source/common/fonts/singlelumpfont.cpp +++ b/source/common/fonts/singlelumpfont.cpp @@ -40,7 +40,7 @@ #include "fontchars.h" #include "printf.h" #include "imagehelpers.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" #include "fontinternals.h" @@ -125,7 +125,8 @@ FSingleLumpFont::FSingleLumpFont (const char *name, const char * lump) FontName = name; - auto data = kloadfile(name, 0); + rawData = fileSystem.LoadFile(lump, 0); + auto& data = rawData; if (data[0] == 0xE1 && data[1] == 0xE6 && data[2] == 0xD5 && data[3] == 0x1A) { @@ -329,7 +330,7 @@ void FSingleLumpFont::LoadFON2 (const char * lump, const uint8_t *data) } else { - Chars[i].TranslatedPic = new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight); + Chars[i].TranslatedPic = new FFontChar2 (rawData, int(data_p - data), widths2[i], FontHeight); TileFiles.AllTiles.Push(Chars[i].TranslatedPic); do { @@ -458,7 +459,7 @@ void FSingleLumpFont::LoadBMF(const char *lump, const uint8_t *data) { // Empty character: skip it. continue; } - auto tex = new FFontChar2(lump, int(chardata + chari + 6 - data), + auto tex = new FFontChar2(rawData, int(chardata + chari + 6 - data), chardata[chari+1], // width chardata[chari+2], // height -(int8_t)chardata[chari+3], // x offset @@ -514,7 +515,7 @@ int FSingleLumpFont::BMFCompare(const void *a, const void *b) void FSingleLumpFont::CheckFON1Chars (double *luminosity) { - auto data = kloadfile(GetName(), 0); + auto &data = rawData; if (data.Size() < 8) return; uint8_t used[256], reverse[256]; @@ -530,7 +531,7 @@ void FSingleLumpFont::CheckFON1Chars (double *luminosity) if(!Chars[i].TranslatedPic) { - Chars[i].TranslatedPic = new FFontChar2 (GetName(), int(data_p - data.Data()), SpaceWidth, FontHeight); + Chars[i].TranslatedPic = new FFontChar2 (rawData, int(data_p - data.Data()), SpaceWidth, FontHeight); Chars[i].XMove = SpaceWidth; TileFiles.AllTiles.Push(Chars[i].TranslatedPic); } diff --git a/source/common/fonts/v_font.cpp b/source/common/fonts/v_font.cpp index 0b14c0348..a11beba66 100644 --- a/source/common/fonts/v_font.cpp +++ b/source/common/fonts/v_font.cpp @@ -93,7 +93,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) FFont *font = FFont::FindFont (name); if (font == nullptr) { - auto lumpy = kopenFileReader(name, 0); + auto lumpy = fileSystem.OpenFileReader(fontlumpname, 0); if (!lumpy.isOpen()) return nullptr; uint32_t head; lumpy.Read (&head, 4); @@ -101,7 +101,8 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) head == MAKE_ID(0xE1,0xE6,0xD5,0x1A)) { FFont *CreateSingleLumpFont (const char *fontname, const char *lump); - return CreateSingleLumpFont (name, name); + lumpy.Close(); + return CreateSingleLumpFont (name, fontlumpname); } } return font; @@ -403,7 +404,7 @@ void V_InitFontColors () TranslationLookup.Clear(); TranslationColors.Clear(); - while ((lump = fileSystem.Iterate("textcolors.txt", &lastlump)) != -1) + while ((lump = fileSystem.Iterate("demolition/textcolors.txt", &lastlump)) != -1) { FScanner sc(lump); while (sc.GetString()) @@ -720,12 +721,8 @@ void V_InitFonts() NewSmallFont = CreateHexLumpFont2("NewSmallFont", "demolition/newconsolefont.hex"); CurrentConsoleFont = NewConsoleFont; - /* - ConFont = V_GetFont("ConsoleFont", "CONFONT"); - { - ConFont = SmallFont; - } - */ + ConFont = V_GetFont("ConsoleFont", "demolition/confont.lmp"); // The con font is needed for the slider graphics + SmallFont = ConFont; // This is so that it doesn't crash and that it immediately gets seen as a proble. The SmallFont should later be mapped to the small game font. } void V_ClearFonts() diff --git a/source/common/fonts/v_font.h b/source/common/fonts/v_font.h index 8c805d57f..0c35c698a 100644 --- a/source/common/fonts/v_font.h +++ b/source/common/fonts/v_font.h @@ -98,7 +98,7 @@ public: virtual ~FFont (); virtual FTexture *GetChar (int code, int translation, int *const width, bool *redirected = nullptr) const; - virtual int GetCharWidth (int code) const; + virtual int CharWidth (int code) const; int GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const; int GetSpaceWidth () const { return SpaceWidth; } int GetHeight () const { return FontHeight; } @@ -168,6 +168,7 @@ protected: uint8_t PatchRemap[256]; FName FontName = NAME_None; + TArray rawData; FFont *Next; static FFont *FirstFont; diff --git a/source/common/fonts/v_text.cpp b/source/common/fonts/v_text.cpp index 3270f3986..e6e3a2ede 100644 --- a/source/common/fonts/v_text.cpp +++ b/source/common/fonts/v_text.cpp @@ -114,7 +114,7 @@ TArray V_BreakLines (FFont *font, int maxwidth, const uint8_t *str lastWasSpace = false; } - nw = font->GetCharWidth (c); + nw = font->CharWidth (c); if ((w > 0 && w + nw > maxwidth) || c == '\n') { // Time to break the line diff --git a/source/common/gamecontrol.cpp b/source/common/gamecontrol.cpp index 4aa39351f..31fe9bf85 100644 --- a/source/common/gamecontrol.cpp +++ b/source/common/gamecontrol.cpp @@ -23,10 +23,20 @@ #include "i_specialpaths.h" #include "z_music.h" #include "statistics.h" +#include "menu.h" +#include "gstrings.h" +#include "quotemgr.h" +#include "mapinfo.h" #ifndef NETCODE_DISABLE #include "enet.h" #endif +MapRecord mapList[512]; // Due to how this gets used it needs to be static. EDuke defines 7 episode plus one spare episode with 64 potential levels each and relies on the static array which is freely accessible by scripts. +MapRecord *currentLevel; // level that is currently played. (The real level, not what script hacks modfifying the current level index can pretend.) +MapRecord* lastLevel; // Same here, for the last level. +MapRecord userMapRecord; // stand-in for the user map. + +void C_CON_SetAliases(); InputState inputState; void SetClipshapes(); int ShowStartupWindow(TArray &); @@ -36,7 +46,8 @@ bool gHaveNetworking; FString currentGame; FString LumpFilter; - +TMap NameToTileIndex; // for assigning names to tiles. The menu accesses this list. By default it gets everything from the dynamic tile map in Duke Nukem and Redneck Rampage. + // Todo: Add additional definition file for the other games or textures not in that list so that the menu does not have to rely on indices. CVAR(Int, cl_defaultconfiguration, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -54,14 +65,16 @@ void UserConfig::ProcessOptions() initprintf("Build-format config files not supported and will be ignored\n"); } +#if 0 // MP disabled pending evaluation auto v = Args->CheckValue("-port"); if (v) netPort = strtol(v, nullptr, 0); netServerMode = Args->CheckParm("-server"); netServerAddress = Args->CheckValue("-connect"); netPassword = Args->CheckValue("-password"); +#endif - v = Args->CheckValue("-addon"); + auto v = Args->CheckValue("-addon"); if (v) { auto val = strtol(v, nullptr, 0); @@ -81,6 +94,22 @@ void UserConfig::ProcessOptions() { gamegrp = "WW2GI.GRP"; } + // Set up all needed content for these two mod which feature a very messy distribution. + // As an alternative they can be zipped up - the launcher will be able to detect and set up such versions automatically. + else if (Args->CheckParm("-route66")) + { + gamegrp = "REDNECK.GRP"; + DefaultCon = "GAME66.CON"; + const char* argv[] = { "tilesa66.art" , "tilesb66.art" }; + AddArt.reset(new FArgs(2, argv)); + } + else if (Args->CheckParm("-cryptic")) + { + gamegrp = "BLOOD.RFF"; + DefaultCon = "CRYPTIC.INI"; + const char* argv[] = { "cpart07.ar_" , "cpart15.ar_" }; + AddArt.reset(new FArgs(2, argv)); + } v = Args->CheckValue("-gamegrp"); if (v) @@ -271,6 +300,42 @@ int GameMain() // //========================================================================== +#define LOCALIZED_STRING(s) "$" s + +void SetDefaultStrings() +{ + // Blood hard codes its skill names, so we have to define them manually. + if (g_gameType & GAMEFLAG_BLOOD) + { + gSkillNames[0] = "$STILL KICKING"; + gSkillNames[1] = "$PINK ON THE INSIDE"; + gSkillNames[2] = "$LIGHTLY BROILED"; + gSkillNames[3] = "$WELL DONE"; + gSkillNames[4] = "$EXTRA CRISPY"; + } + + //Set a few quotes which are used for common handling of a few status messages + quoteMgr.InitializeQuote(23, "$MESSAGES: ON"); + quoteMgr.InitializeQuote(24, "$MESSAGES: OFF"); + quoteMgr.InitializeQuote(83, "$FOLLOW MODE OFF"); + quoteMgr.InitializeQuote(84, "$FOLLOW MODE ON"); + quoteMgr.InitializeQuote(85, "$AUTORUNOFF"); + quoteMgr.InitializeQuote(86, "$AUTORUNON"); + #if 0 // todo: print a message + if (gAutoRun) + viewSetMessage("Auto run ON"); + else + viewSetMessage("Auto run OFF"); + + #endif +} + +//========================================================================== +// +// +// +//========================================================================== + int CONFIG_Init() { SetClipshapes(); @@ -369,10 +434,18 @@ int CONFIG_Init() CheckFrontend(g_gameType); InitFileSystem(usedgroups); + TArray addArt; + for (auto& grp : usedgroups) + { + for (auto& art : grp.FileInfo.loadart) + { + addArt.Push(art); + } + } + TileFiles.AddArt(addArt); CONTROL_ClearAssignments(); CONFIG_InitMouseAndController(); - CONFIG_SetGameControllerDefaultsStandard(); CONFIG_SetDefaultKeys(cl_defaultconfiguration == 1 ? "demolition/origbinds.txt" : cl_defaultconfiguration == 2 ? "demolition/leftbinds.txt" : "demolition/defbinds.txt"); G_ReadConfig(currentGame); @@ -385,13 +458,14 @@ int CONFIG_Init() { playername = userConfig.CommandName; } + GStrings.LoadStrings(); V_InitFonts(); - buttonMap.SetGameAliases(); + C_CON_SetAliases(); Mus_Init(); InitStatistics(); - - - + M_Init(); + SetDefaultStrings(); + if (g_gameType & GAMEFLAG_RR) InitRREndMap(); // this needs to be done better later return gi->app_main(); } @@ -452,7 +526,7 @@ int32_t CONFIG_GetMapBestTime(char const* const mapname, uint8_t const* const ma if (GameConfig->SetSection("MapTimes")) { auto s = GameConfig->GetValueForKey(m); - if (s) (int)strtoull(s, nullptr, 0); + if (s) return (int)strtoull(s, nullptr, 0); } return -1; } @@ -473,7 +547,6 @@ int CONFIG_SetMapBestTime(uint8_t const* const mapmd4, int32_t tm) // //========================================================================== -int32_t MouseDigitalFunctions[MAXMOUSEAXES][2]; int32_t MouseAnalogueAxes[MAXMOUSEAXES]; int32_t JoystickFunctions[MAXJOYBUTTONSANDHATS][2]; int32_t JoystickDigitalFunctions[MAXJOYAXES][2]; @@ -490,51 +563,6 @@ static const char* mouseanalogdefaults[MAXMOUSEAXES] = }; -static const char* mousedigitaldefaults[MAXMOUSEDIGITAL] = -{ -}; - -static const char* joystickdefaults[MAXJOYBUTTONSANDHATS] = -{ -"Fire", -"Strafe", -"Run", -"Open", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"", -"Aim_Down", -"Look_Right", -"Aim_Up", -"Look_Left", -}; - - static const char* joystickclickeddefaults[MAXJOYBUTTONSANDHATS] = { "", @@ -552,18 +580,6 @@ static const char* joystickanalogdefaults[MAXJOYAXES] = }; -static const char* joystickdigitaldefaults[MAXJOYDIGITAL] = -{ -"", -"", -"", -"", -"", -"", -"Run", -}; - - //========================================================================== // // @@ -627,62 +643,6 @@ void CONFIG_SetupMouse(void) void CONFIG_SetupJoystick(void) { - const char* val; - FString section = currentGame + ".ControllerSettings"; - if (!GameConfig->SetSection(section)) return; - - for (int i = 0; i < MAXJOYBUTTONSANDHATS; i++) - { - section.Format("ControllerButton%d", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickFunctions[i][0] = buttonMap.FindButtonIndex(val); - - section.Format("ControllerButtonClicked%d", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickFunctions[i][1] = buttonMap.FindButtonIndex(val); - } - - // map over the axes - for (int i = 0; i < MAXJOYAXES; i++) - { - section.Format("ControllerAnalogAxes%d", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickAnalogueAxes[i] = CONFIG_AnalogNameToNum(val); - - section.Format("ControllerDigitalAxes%d_0", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickDigitalFunctions[i][0] = buttonMap.FindButtonIndex(val); - - section.Format("ControllerDigitalAxes%d_1", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickDigitalFunctions[i][1] = buttonMap.FindButtonIndex(val); - - section.Format("ControllerAnalogScale%d", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickAnalogueScale[i] = (int32_t)strtoull(val, nullptr, 0); - - section.Format("ControllerAnalogInvert%d", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickAnalogueInvert[i] = (int32_t)strtoull(val, nullptr, 0); - - section.Format("ControllerAnalogDead%d", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickAnalogueDead[i] = (int32_t)strtoull(val, nullptr, 0); - - section.Format("ControllerAnalogSaturate%d", i); - val = GameConfig->GetValueForKey(section); - if (val) - JoystickAnalogueSaturate[i] = (int32_t)strtoull(val, nullptr, 0); - } - for (int i = 0; i < MAXJOYAXES; i++) { CONTROL_MapAnalogAxis(i, JoystickAnalogueAxes[i], controldevice_joystick); @@ -803,220 +763,15 @@ static void CONFIG_SetGameControllerAxesModern() analogAxis.apply(); } -void CONFIG_SetGameControllerDefaultsStandard() -{ - CONFIG_SetGameControllerDefaultsClear(); - CONFIG_SetGameControllerAxesModern(); - - static GameControllerButtonSetting const buttons[] = - { - { GAMECONTROLLER_BUTTON_A, gamefunc_Jump }, - { GAMECONTROLLER_BUTTON_B, gamefunc_Toggle_Crouch }, - { GAMECONTROLLER_BUTTON_BACK, gamefunc_Map }, - { GAMECONTROLLER_BUTTON_LEFTSTICK, gamefunc_Run }, - { GAMECONTROLLER_BUTTON_RIGHTSTICK, gamefunc_Quick_Kick }, - { GAMECONTROLLER_BUTTON_LEFTSHOULDER, gamefunc_Crouch }, - { GAMECONTROLLER_BUTTON_RIGHTSHOULDER, gamefunc_Jump }, - { GAMECONTROLLER_BUTTON_DPAD_UP, gamefunc_Previous_Weapon }, - { GAMECONTROLLER_BUTTON_DPAD_DOWN, gamefunc_Next_Weapon }, - }; - - static GameControllerButtonSetting const buttonsDuke[] = - { - { GAMECONTROLLER_BUTTON_X, gamefunc_Open }, - { GAMECONTROLLER_BUTTON_Y, gamefunc_Inventory }, - { GAMECONTROLLER_BUTTON_DPAD_LEFT, gamefunc_Inventory_Left }, - { GAMECONTROLLER_BUTTON_DPAD_RIGHT, gamefunc_Inventory_Right }, - }; - - static GameControllerButtonSetting const buttonsFury[] = - { - { GAMECONTROLLER_BUTTON_X, gamefunc_Steroids }, // Reload - { GAMECONTROLLER_BUTTON_Y, gamefunc_Open }, - { GAMECONTROLLER_BUTTON_DPAD_LEFT, gamefunc_MedKit }, - { GAMECONTROLLER_BUTTON_DPAD_RIGHT, gamefunc_NightVision }, // Radar - }; - - static GameControllerDigitalAxisSetting const digitalAxes[] = - { - { GAMECONTROLLER_AXIS_TRIGGERLEFT, 1, gamefunc_Alt_Fire }, - { GAMECONTROLLER_AXIS_TRIGGERRIGHT, 1, gamefunc_Fire }, - }; - - for (auto const& button : buttons) - button.apply(); - - /* - if (FURY) - { - for (auto const& button : buttonsFury) - button.apply(); - } - else - */ - { - for (auto const& button : buttonsDuke) - button.apply(); - } - - for (auto const& digitalAxis : digitalAxes) - digitalAxis.apply(); -} - -void CONFIG_SetGameControllerDefaultsPro() -{ - CONFIG_SetGameControllerDefaultsClear(); - CONFIG_SetGameControllerAxesModern(); - - static GameControllerButtonSetting const buttons[] = - { - { GAMECONTROLLER_BUTTON_A, gamefunc_Open }, - { GAMECONTROLLER_BUTTON_B, gamefunc_Third_Person_View }, - { GAMECONTROLLER_BUTTON_Y, gamefunc_Quick_Kick }, - { GAMECONTROLLER_BUTTON_BACK, gamefunc_Map }, - { GAMECONTROLLER_BUTTON_LEFTSTICK, gamefunc_Run }, - { GAMECONTROLLER_BUTTON_RIGHTSTICK, gamefunc_Crouch }, - { GAMECONTROLLER_BUTTON_DPAD_UP, gamefunc_Previous_Weapon }, - { GAMECONTROLLER_BUTTON_DPAD_DOWN, gamefunc_Next_Weapon }, - }; - - static GameControllerButtonSetting const buttonsDuke[] = - { - { GAMECONTROLLER_BUTTON_X, gamefunc_Inventory }, - { GAMECONTROLLER_BUTTON_LEFTSHOULDER, gamefunc_Previous_Weapon }, - { GAMECONTROLLER_BUTTON_RIGHTSHOULDER, gamefunc_Next_Weapon }, - { GAMECONTROLLER_BUTTON_DPAD_LEFT, gamefunc_Inventory_Left }, - { GAMECONTROLLER_BUTTON_DPAD_RIGHT, gamefunc_Inventory_Right }, - }; - - static GameControllerButtonSetting const buttonsFury[] = - { - { GAMECONTROLLER_BUTTON_X, gamefunc_Steroids }, // Reload - { GAMECONTROLLER_BUTTON_LEFTSHOULDER, gamefunc_Crouch }, - { GAMECONTROLLER_BUTTON_RIGHTSHOULDER, gamefunc_Alt_Fire }, - { GAMECONTROLLER_BUTTON_DPAD_LEFT, gamefunc_MedKit }, - { GAMECONTROLLER_BUTTON_DPAD_RIGHT, gamefunc_NightVision }, // Radar - }; - - static GameControllerDigitalAxisSetting const digitalAxes[] = - { - { GAMECONTROLLER_AXIS_TRIGGERLEFT, 1, gamefunc_Jump }, - { GAMECONTROLLER_AXIS_TRIGGERRIGHT, 1, gamefunc_Fire }, - }; - - for (auto const& button : buttons) - button.apply(); - -#if 0 // ouch... - if (FURY) - { - for (auto const& button : buttonsFury) - button.apply(); - } - else -#endif - { - for (auto const& button : buttonsDuke) - button.apply(); - } - - for (auto const& digitalAxis : digitalAxes) - digitalAxis.apply(); -} - -FString CONFIG_GetGameFuncOnKeyboard(int gameFunc) -{ - auto binding = buttonMap.GetButtonAlias(gameFunc); - auto keys = Bindings.GetKeysForCommand(binding); - for(auto key : keys) - { - if (key < KEY_FIRSTMOUSEBUTTON) - { - auto scan = KB_ScanCodeToString(key); - if (scan) return scan; - - } - } - return ""; -} - -FString CONFIG_GetGameFuncOnMouse(int gameFunc) -{ - auto binding = buttonMap.GetButtonAlias(gameFunc); - auto keys = Bindings.GetKeysForCommand(binding); - for (auto key : keys) - { - if ((key >= KEY_FIRSTMOUSEBUTTON && key < KEY_FIRSTJOYBUTTON) || (key >= KEY_MWHEELUP && key <= KEY_MWHEELLEFT)) - { - auto scan = KB_ScanCodeToString(key); - if (scan) return scan; - - } - } - return ""; -} - -char const* CONFIG_GetGameFuncOnJoystick(int gameFunc) -{ - auto binding = buttonMap.GetButtonAlias(gameFunc); - auto keys = Bindings.GetKeysForCommand(binding); - for (auto key : keys) - { - if (key >= KEY_FIRSTJOYBUTTON && !(key >= KEY_MWHEELUP && key <= KEY_MWHEELLEFT)) - { - auto scan = KB_ScanCodeToString(key); - if (scan) return scan; - } - } - return ""; -} - -// FIXME: Consider the mouse as well! -FString CONFIG_GetBoundKeyForLastInput(int gameFunc) -{ - if (CONTROL_LastSeenInput == LastSeenInput::Joystick) - { - FString name = CONFIG_GetGameFuncOnJoystick(gameFunc); - if (name.IsNotEmpty()) - { - return name; - } - } - - FString name = CONFIG_GetGameFuncOnKeyboard(gameFunc); - if (name.IsNotEmpty()) - { - return name; - } - - name = CONFIG_GetGameFuncOnMouse(gameFunc); - if (name.IsNotEmpty()) - { - return name; - } - - name = CONFIG_GetGameFuncOnJoystick(gameFunc); - if (name.IsNotEmpty()) - { - return name; - } - return "UNBOUND"; -} void CONFIG_InitMouseAndController() { - memset(MouseDigitalFunctions, -1, sizeof(MouseDigitalFunctions)); memset(JoystickFunctions, -1, sizeof(JoystickFunctions)); memset(JoystickDigitalFunctions, -1, sizeof(JoystickDigitalFunctions)); for (int i = 0; i < MAXMOUSEAXES; i++) { - MouseDigitalFunctions[i][0] = buttonMap.FindButtonIndex(mousedigitaldefaults[i * 2]); - MouseDigitalFunctions[i][1] = buttonMap.FindButtonIndex(mousedigitaldefaults[i * 2 + 1]); - CONTROL_MapDigitalAxis(i, MouseDigitalFunctions[i][0], 0, controldevice_mouse); - CONTROL_MapDigitalAxis(i, MouseDigitalFunctions[i][1], 1, controldevice_mouse); - MouseAnalogueAxes[i] = CONFIG_AnalogNameToNum(mouseanalogdefaults[i]); CONTROL_MapAnalogAxis(i, MouseAnalogueAxes[i], controldevice_mouse); } @@ -1043,20 +798,6 @@ void CONFIG_WriteControllerSettings() { FString section = currentGame + ".ControllerSettings"; GameConfig->SetSection(section); - for (int dummy = 0; dummy < MAXJOYBUTTONSANDHATS; dummy++) - { - if (buttonMap.GetButtonName(JoystickFunctions[dummy][0])) - { - buf.Format("ControllerButton%d", dummy); - GameConfig->SetValueForKey(buf, buttonMap.GetButtonName(JoystickFunctions[dummy][0])); - } - - if (buttonMap.GetButtonName(JoystickFunctions[dummy][1])) - { - buf.Format("ControllerButtonClicked%d", dummy); - GameConfig->SetValueForKey(buf, buttonMap.GetButtonName(JoystickFunctions[dummy][1])); - } - } for (int dummy = 0; dummy < MAXJOYAXES; dummy++) { if (CONFIG_AnalogNumToName(JoystickAnalogueAxes[dummy])) @@ -1065,12 +806,6 @@ void CONFIG_WriteControllerSettings() GameConfig->SetValueForKey(buf, CONFIG_AnalogNumToName(JoystickAnalogueAxes[dummy])); } - if (buttonMap.GetButtonName(JoystickDigitalFunctions[dummy][0])) - { - buf.Format("ControllerDigitalAxes%d_0", dummy); - GameConfig->SetValueForKey(buf, buttonMap.GetButtonName(JoystickDigitalFunctions[dummy][0])); - } - if (buttonMap.GetButtonName(JoystickDigitalFunctions[dummy][1])) { buf.Format("ControllerDigitalAxes%d_1", dummy); diff --git a/source/common/gamecontrol.h b/source/common/gamecontrol.h index 13905fb1c..31955c8f1 100644 --- a/source/common/gamecontrol.h +++ b/source/common/gamecontrol.h @@ -7,6 +7,8 @@ #include "zstring.h" #include "inputstate.h" #include "gamecvars.h" +#include "tarray.h" +#include "name.h" EXTERN_CVAR(Int, cl_defaultconfiguration) @@ -14,6 +16,8 @@ extern FString currentGame; extern FString LumpFilter; class FArgs; +extern TMap NameToTileIndex; + void D_AddWildFile(TArray& wadfiles, const char* value); int CONFIG_Init(); @@ -34,29 +38,12 @@ void CONFIG_SetDefaultKeys(const char *defbinds); #define DEFAULTJOYSTICKANALOGUESATURATE 9500 -extern int32_t MouseDigitalFunctions[MAXMOUSEAXES][2]; -extern int32_t MouseAnalogueAxes[MAXMOUSEAXES]; -extern int32_t JoystickFunctions[MAXJOYBUTTONSANDHATS][2]; -extern int32_t JoystickDigitalFunctions[MAXJOYAXES][2]; -extern int32_t JoystickAnalogueAxes[MAXJOYAXES]; -extern int32_t JoystickAnalogueScale[MAXJOYAXES]; -extern int32_t JoystickAnalogueDead[MAXJOYAXES]; -extern int32_t JoystickAnalogueSaturate[MAXJOYAXES]; -extern int32_t JoystickAnalogueInvert[MAXJOYAXES]; - -int32_t CONFIG_AnalogNameToNum(const char* func); -const char* CONFIG_AnalogNumToName(int32_t func); -void CONFIG_SetupMouse(void); void CONFIG_SetupJoystick(void); void CONFIG_WriteControllerSettings(); void CONFIG_InitMouseAndController(); -void CONFIG_SetGameControllerDefaultsStandard(); -void CONFIG_SetGameControllerDefaultsPro(); void CONFIG_SetGameControllerDefaultsClear(); -FString CONFIG_GetBoundKeyForLastInput(int gameFunc); - extern FStringCVar* const CombatMacros[]; void CONFIG_ReadCombatMacros(); @@ -96,7 +83,7 @@ extern UserConfig userConfig; inline bool MusicEnabled() { - return mus_enabled && !userConfig.nomusic; + return !userConfig.nomusic; } inline bool SoundEnabled() diff --git a/source/common/gamecvars.cpp b/source/common/gamecvars.cpp index 181c55b7a..5a4674b13 100644 --- a/source/common/gamecvars.cpp +++ b/source/common/gamecvars.cpp @@ -47,6 +47,9 @@ #include "rts.h" #include "stats.h" #include "z_music.h" +#include "c_dispatch.h" +#include "gstrings.h" +#include "quotemgr.h" /* Notes @@ -59,7 +62,16 @@ CVARD(Bool, cl_crosshair, true, CVAR_ARCHIVE, "enable/disable crosshair"); CVARD(Bool, cl_automsg, false, CVAR_ARCHIVE, "enable/disable automatically sending messages to all players") // Not implemented for Blood CVARD(Bool, cl_autorun, true, CVAR_ARCHIVE, "enable/disable autorun") + CVARD(Bool, cl_runmode, true, CVAR_ARCHIVE, "enable/disable modernized run key operation") + +bool G_CheckAutorun(bool button) +{ + if (cl_runmode) return button || cl_autorun; + else return button ^ !!cl_autorun; +} + + CVARD(Bool, cl_autosave, true, CVAR_ARCHIVE, "enable/disable autosaves") // Not implemented for Blood (but looks like the other games never check it either.) CVARD(Bool, cl_autosavedeletion, true, CVAR_ARCHIVE, "enable/disable automatic deletion of autosaves") // Not implemented for Blood CVARD(Int, cl_maxautosaves, 8, CVAR_ARCHIVE, "number of autosaves to keep before deleting the oldest") // Not implemented for Blood @@ -106,12 +118,6 @@ CUSTOM_CVARD(Int, cl_autovote, 0, CVAR_ARCHIVE, "enable/disable automatic voting if (self < 0 || self > 2) self = 0; } -bool G_CheckAutorun(bool button) -{ - if (cl_runmode) return button || cl_autorun; - else return button ^ !!cl_autorun; -} - // Demos CVARD_NAMED(Bool, demorec_diffcompress, demorec_diffcompress_cvar, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "Compression for diffs") @@ -124,12 +130,14 @@ CVARD(Bool, demoplay_showsync, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enable/dis // Sound -CVARD(Bool, snd_ambience, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enables/disables ambient sounds") // Not implemented for Blood +CUSTOM_CVARD(Bool, snd_ambience, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL, "enables/disables ambient sounds") // Not implemented for Blood +{ + gi->SetAmbience(self); +} CVARD(Bool, snd_enabled, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enables/disables sound effects") CVARD(Bool, snd_tryformats, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enables/disables automatic discovery of replacement sounds and music in .flac and .ogg formats") CVARD(Bool, snd_doppler, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enable/disable 3d sound") -CVARD(Bool, mus_enabled, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enables/disables music") CVARD(Bool, mus_restartonload, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "restart the music when loading a saved game with the same map or not") // only implemented for Blood - todo: generalize CVARD(Bool, mus_redbook, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_FRONTEND_BLOOD, "enables/disables redbook audio (Blood only!)") // only Blood has assets for this. @@ -168,14 +176,6 @@ CUSTOM_CVARD(Int, snd_speech, 5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enables/disabl else if (self > 5) self = 5; } -int MusicDevice = ASS_WinMM; -CUSTOM_CVARD(Int, mus_device, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "selects music device") -{ - if (self < 0) self = 0; - else if (self > 1) self = 1; - else MusicDevice = self? ASS_WinMM : ASS_OPL3; // must be copied because it gets altered by the music code. -} - // HUD @@ -209,17 +209,17 @@ bool G_ChangeHudLayout(int direction) { int layout = hud_size - 1; while (!gi->validate_hud(layout) && layout >= 0) layout--; - if (layout >= 0) + if (layout >= 0 && layout < hud_size && gi->validate_hud(layout)) { hud_size = layout; return true; } } - else if (hud_size < 11) + else if (direction > 0 && hud_size < 11) { int layout = hud_size + 1; while (!gi->validate_hud(layout) && layout <= 11) layout++; - if (layout <= 11) + if (layout <= 11 && layout > hud_size && gi->validate_hud(layout)) { hud_size = layout; return true; @@ -240,8 +240,28 @@ CVARD(Bool, hud_showmapname, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enable/disab CVARD(Bool, hud_position, false, CVAR_ARCHIVE, "aligns the status bar to the bottom/top") CVARD(Bool, hud_bgstretch, false, CVAR_ARCHIVE|CVAR_FRONTEND_DUKELIKE, "enable/disable background image stretching in wide resolutions") CVARD(Int, hud_messagetime, 120, CVAR_ARCHIVE|CVAR_FRONTEND_DUKELIKE, "length of time to display multiplayer chat messages") -// Should be available to all games - the message handling should also be consolidated into a game independent feature. -/*CUSTOM_*/CVARD(Bool, hud_messages, true, CVAR_ARCHIVE | CVAR_FRONTEND_BLOOD|CVAR_FRONTEND_SHADOWWARRIOR, "enable/disable showing messages") +CUSTOM_CVARD(Int, hud_messages, 1, CVAR_ARCHIVE, "enable/disable showing messages") +{ + if (self < 0 || self > 2) self = 1; +} + +// This cannot be done with the 'toggle' CCMD because it needs to control itself when to output the message +CCMD (togglemessages) +{ + if (hud_messages) + { + gi->PrintMessage(PRINT_MEDIUM, "%s\n", quoteMgr.GetQuote(24)); + hud_messages = false; + } + else + { + hud_messages = true; + gi->PrintMessage(PRINT_MEDIUM, "%s\n", quoteMgr.GetQuote(23)); + } +} + + + //{ //Blood::gGameMessageMgr.SetState(self); // this is for terminaing an active message. Cannot be done like this because CVARs are global. //} @@ -282,14 +302,19 @@ CUSTOM_CVARD(Bool, in_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCAL CONTROL_MouseEnabled = (self && CONTROL_MousePresent); } -// Does it even make sense to have this configurable? It is in the menu but can be switched around at will by the mouse input code. -int32_t g_MyAimMode = 1; -CUSTOM_CVARD(Bool, in_mousemode, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "toggles vertical mouse view") +CVARD(Bool, in_mousemode, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "toggles vertical mouse view") + +CVAR(Bool, silentmouseaimtoggle, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) + +CCMD(togglemouseaim) { - g_MyAimMode = self; // Needs to be copied to a shadow variable because the input code messes around with this setting - but that should not affect the user's original choice. + in_mousemode = !in_mousemode; + if (!silentmouseaimtoggle) + { + gi->DoPrintMessage(PRINT_MEDIUM, in_mousemode? GStrings("TXT_MOUSEAIMON") : GStrings("TXT_MOUSEAIMOFF")); + } } -CVARD(Bool, in_aimmode, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "0:toggle, 1:hold to aim") CVARD(Bool, in_mouseflip, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "invert vertical mouse movement") CUSTOM_CVARD(Int, in_mousebias, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE, "emulates the original mouse code's weighting of input towards whichever axis is moving the most at any given time") @@ -306,22 +331,22 @@ CUSTOM_CVARD(Int, in_mousedeadzone, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE, "amount o CVARD(Bool, in_mousesmoothing, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE, "enable/disable mouse input smoothing") -CUSTOM_CVARD(Float, in_mousesensitivity, DEFAULTMOUSESENSITIVITY, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "changes the mouse sensitivity") +CUSTOM_CVARD(Float, in_mousesensitivity, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "changes the mouse sensitivity") { if (self < 0) self = 0; - else if (self > 25) self = 25; + else if (self > 6) self = 6; } -CUSTOM_CVARD(Int, in_mousescalex, 65536, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "changes the mouse sensitivity") +CUSTOM_CVARD(Float, in_mousescalex, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "changes the mouse sensitivity") { - if (self < -4*65536) self = 4 * 65536; - else if (self > 4 * 65536) self = 4 * 65536; + if (self < -4) self = 4; + else if (self > 4) self = 4; } -CUSTOM_CVARD(Int, in_mousescaley, 65536, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "changes the mouse sensitivity") +CUSTOM_CVARD(Float, in_mousescaley, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "changes the mouse sensitivity") { - if (self < -4 * 65536) self = 4 * 65536; - else if (self > 4 * 65536) self = 4 * 65536; + if (self < -4) self = 4; + else if (self > 4) self = 4; } @@ -488,6 +513,30 @@ CUSTOM_CVARD(Float, vid_brightness, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "adju // todo: tell the system to update } + +CUSTOM_CVARD(Float, vid_saturation, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "adjusts saturation component of gamma ramp") +{ + if (self < -3) self = -3; + else if (self > 3) self = 3; + // todo: tell the system to update +} + +CVAR(Int, gl_satformula, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); + +CCMD (bumpgamma) +{ + // [RH] Gamma correction tables are now generated on the fly for *any* gamma level + // Q: What are reasonable limits to use here? + + float newgamma = vid_gamma + 0.1f; + + if (newgamma > 3.0) + newgamma = 1.0; + + vid_gamma = newgamma; + Printf ("Gamma correction level %g\n", newgamma); +} + //{ "vid_contrast","adjusts contrast component of gamma ramp",(void *) &vid_contrast, CVAR_FLOAT|CVAR_FUNCPTR, 0, 10 }, //{ "vid_brightness","adjusts brightness component of gamma ramp",(void *) &vid_brightness, CVAR_FLOAT|CVAR_FUNCPTR, 0, 10 }, @@ -499,32 +548,44 @@ CUSTOM_CVAR(String, rtsname, "", CVAR_ARCHIVE | CVAR_USERINFO) CVAR(String, usermapfolder, "", CVAR_ARCHIVE); +CUSTOM_CVAR(Int, playercolor, 0, CVAR_ARCHIVE|CVAR_USERINFO) +{ + if (self < 0 || self > 10) self = 0; + else ;// gi->UpdatePlayerColor(); // this part is game specific +} + +CUSTOM_CVAR(Int, playerteam, 0, CVAR_USERINFO) // this one is transient and won't be saved. +{ + if (self < 0 || self > 3) self = 0; + else ;// gi->UpdatePlayerTeam(); // this part is game specific +} + +// Will only become useful if the obituary system gets overhauled and for localization +CUSTOM_CVAR(Int, playergender, 0, CVAR_USERINFO|CVAR_ARCHIVE) +{ + if (self < 0 || self > 3) self = 0; +} // Internal settings for demo recording and the multiplayer menu. These won't get saved and only are CVARs so that the menu code can use them. CVAR(Bool, m_recstat, false, CVAR_NOSET) CVAR(Int, m_coop, 0, CVAR_NOSET) CVAR(Int, m_ffire, 1, CVAR_NOSET) +CVAR(Int, m_monsters, 1, CVAR_NOSET) CVAR(Int, m_marker, 1, CVAR_NOSET) CVAR(Int, m_level_number, 0, CVAR_NOSET) +CVAR(Int, m_episode_number, 0, CVAR_NOSET) CVAR(Int, m_noexits, 0, CVAR_NOSET) -CVAR(Int, playercolor, 0, CVAR_NOSET) -CVAR(Int, playerteam, 0, CVAR_NOSET) +CVAR(String, m_server, "localhost", CVAR_NOSET) +CVAR(String, m_netport, "19014", CVAR_NOSET) #if 0 -// These have to wait until the HUD code is cleaned up (no idea which may survive and which won't.) /* // Currently unavailable due to dependency on an obsolete OpenGL feature { "deliriumblur", "enable/disable delirium blur effect(polymost)", (void *)&gDeliriumBlur, CVAR_BOOL, 0, 1 }, - if (!Bstrcasecmp(parm->name, "color")) - { - playercolor = G_CheckPlayerColor(playercolor); - g_player[0].ps->palookup = g_player[0].pcolor = playercolor; - } - // This one gets changed at run time by the game code, so making it persistent does not work // This option is not really useful anymore @@ -533,9 +594,6 @@ CVAR(Int, playerteam, 0, CVAR_NOSET) // This requires a different approach, because it got used like a CCMD, not a CVAR. { "skill","changes the game skill setting", (void *)&ud.m_player_skill, CVAR_INT|CVAR_FUNCPTR|CVAR_NOSAVE/*|CVAR_NOMULTI*/, 0, 5 }, - // requires cleanup first - //{ "team","change team in multiplayer", (void *)&playerteam, CVAR_INT|CVAR_MULTI, 0, 3 }, - // just as a reminder: /* else if (!Bstrcasecmp(parm->name, "vid_gamma")) diff --git a/source/common/gamecvars.h b/source/common/gamecvars.h index 1b9265c47..45463e313 100644 --- a/source/common/gamecvars.h +++ b/source/common/gamecvars.h @@ -46,9 +46,7 @@ EXTERN_CVAR(Int, snd_mixrate) EXTERN_CVAR(Int, snd_numchannels) EXTERN_CVAR(Int, snd_numvoices) EXTERN_CVAR(Int, snd_speech) -EXTERN_CVAR(Int, mus_volume) EXTERN_CVAR(Int, mus_device) -extern int MusicDevice; EXTERN_CVAR(Int, hud_layout) EXTERN_CVAR(Int, hud_scale) @@ -63,7 +61,7 @@ EXTERN_CVAR(Int, hud_messagetime) EXTERN_CVAR(Bool, hud_glowingquotes) EXTERN_CVAR(Int, hud_textscale) EXTERN_CVAR(Int, hud_weaponscale) -EXTERN_CVAR(Bool, hud_messages) +EXTERN_CVAR(Int, hud_messages) EXTERN_CVAR(Int, althud_numbertile) EXTERN_CVAR(Int, althud_numberpal) @@ -90,16 +88,14 @@ EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Bool, in_joystick) EXTERN_CVAR(Bool, in_mouse) -EXTERN_CVAR(Bool, in_aimmode) EXTERN_CVAR(Int, in_mousebias) EXTERN_CVAR(Int, in_mousedeadzone) EXTERN_CVAR(Bool, in_mouseflip) EXTERN_CVAR(Bool, in_mousemode) EXTERN_CVAR(Bool, in_mousesmoothing) EXTERN_CVAR(Float, in_mousesensitivity) -EXTERN_CVAR(Int, in_mousescalex) -EXTERN_CVAR(Int, in_mousescaley) -extern int32_t g_MyAimMode; +EXTERN_CVAR(Float, in_mousescalex) +EXTERN_CVAR(Float, in_mousescaley) EXTERN_CVAR(Bool, in_mousemode) EXTERN_CVAR(String, wchoice) diff --git a/source/common/initfs.cpp b/source/common/initfs.cpp index cb9bda281..6f46b4892 100644 --- a/source/common/initfs.cpp +++ b/source/common/initfs.cpp @@ -129,7 +129,7 @@ bool D_AddFile (TArray &wadfiles, const char *file, bool check = true, if (check && !DirEntryExists (file)) { - const char *f = BaseFileSearch (file, ".wad", false); + const char *f = BaseFileSearch (file, ".grp", false); if (f == NULL) { Printf ("Can't find '%s'\n", file); @@ -267,7 +267,7 @@ static void D_AddDirectory (TArray &wadfiles, const char *dir) { skindir[stuffstart++] = '/'; int savedstart = stuffstart; - const char* validexts[] = { "*.grp", "*.zip", "*.pk3", "*.pk4", "*.7z", "*.pk7", "*.dat" }; + static const char* validexts[] = { "*.grp", "*.zip", "*.pk3", "*.pk4", "*.7z", "*.pk7", "*.dat" }; for (auto ext : validexts) { stuffstart = savedstart; diff --git a/source/common/inputstate.cpp b/source/common/inputstate.cpp index 4036dfc0f..f5a3e6ced 100644 --- a/source/common/inputstate.cpp +++ b/source/common/inputstate.cpp @@ -40,8 +40,34 @@ void InputState::GetMouseDelta(ControlInfo * info) last = input; } - info->mousex = int(finput.x * (4.f / 65536.f) * in_mousesensitivity * in_mousescalex); - info->mousey = int(finput.y * (4.f / 65536.f) * in_mousesensitivity * in_mousescaley); + info->mousex = int(finput.x * (16.f) * in_mousesensitivity * in_mousescalex); + info->mousey = int(finput.y * (16.f) * in_mousesensitivity * in_mousescaley); + + // todo: Use these when the mouse is used for moving instead of turning. + //info->mousex = int(finput.x * (4.f) * in_mousesensitivity * in_mouseside); + //info->mousey = int(finput.y * (4.f) * in_mousesensitivity * in_mouseforward); + + if (in_mousedeadzone) + { + if (info->mousey > 0) + info->mousey = max(info->mousey - in_mousedeadzone, 0); + else if (info->mousey < 0) + info->mousey = min(info->mousey + in_mousedeadzone, 0); + + if (info->mousex > 0) + info->mousex = max(info->mousex - in_mousedeadzone, 0); + else if (info->mousex < 0) + info->mousex = min(info->mousex + in_mousedeadzone, 0); + } + + if (in_mousebias) + { + if (abs(info->mousex) > abs(info->mousey)) + info->mousey = tabledivide32_noinline(info->mousey, in_mousebias); + else + info->mousex = tabledivide32_noinline(info->mousex, in_mousebias); + } + } void InputState::AddEvent(const event_t *ev) diff --git a/source/common/inputstate.h b/source/common/inputstate.h index d16cf78a5..4639e2a5e 100644 --- a/source/common/inputstate.h +++ b/source/common/inputstate.h @@ -302,6 +302,13 @@ public: int32_t mouseReadAbs(vec2_t* const pResult); void GetMouseDelta(ControlInfo* info); + void ClearAllInput() + { + ClearKeysDown(); + keyFlushChars(); + keyFlushScans(); + } + }; diff --git a/source/common/mapinfo.h b/source/common/mapinfo.h new file mode 100644 index 000000000..abff2ba2f --- /dev/null +++ b/source/common/mapinfo.h @@ -0,0 +1,79 @@ +#pragma once + +#include "gstrings.h" +#include "cmdlib.h" +#include "quotemgr.h" +#ifdef GetMessage +#undef GetMessage // Windows strikes... +#endif + +// Localization capable replacement of the game specific solutions. + +inline void MakeStringLocalizable(FString "e) +{ + // Only prepend a quote if the string is localizable. + if (quote.Len() > 0 && quote[0] != '$' && GStrings[quote]) quote.Insert(0, "$"); +} + +enum +{ + MI_FORCEEOG = 1, +}; + +struct MapRecord +{ + int parTime = -1; + int designerTime = -1; + FString fileName; + FString labelName; + FString name; + FString music; + int cdSongId = -1; + int flags = 0; + + // The rest is only used by Blood + int nextLevel = -1; + int nextSecret = -1; + int messageStart = 0; // messages are stored in the quote array to reduce clutter. + FString author; + int8_t fog = -1, weather = -1; // Blood defines these but they aren't used. + + const char *DisplayName() + { + if (name.IsEmpty()) return labelName; + return GStrings.localize(name); + } + void SetName(const char *n) + { + name = n; + MakeStringLocalizable(name); + } + void SetFileName(const char* n) + { + fileName = n; + labelName = ExtractFileBase(n); + } + const char* GetMessage(int num) + { + return quoteMgr.GetQuote(messageStart + num); + } + +}; + +extern MapRecord mapList[512]; +extern MapRecord userMapRecord; +extern MapRecord *currentLevel; +extern MapRecord* lastLevel; + + +inline void InitRREndMap() +{ + // RR defines its end map ad-hoc so give it a proper entry to reference (the last one in episode 2 because it needs to be in Ep. 2.) + mapList[127].SetName("$TXT_CLOSEENCOUNTERS"); + mapList[127].SetFileName("endmap.map"); +} + +enum +{ + RRENDSLOT = 127 +}; \ No newline at end of file diff --git a/source/common/menu/imagescroller.cpp b/source/common/menu/imagescroller.cpp new file mode 100644 index 000000000..92bb9220d --- /dev/null +++ b/source/common/menu/imagescroller.cpp @@ -0,0 +1,165 @@ +/* +** imagescroller.cpp +** Scrolls through multiple fullscreen image pages, +** +**--------------------------------------------------------------------------- +** Copyright 2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "v_font.h" +#include "cmdlib.h" +#include "gstrings.h" +#include "d_gui.h" +#include "d_event.h" +#include "menu.h" +#include "v_draw.h" +#include "baselayer.h" +#include "gamecontrol.h" +#include "build.h" + +//============================================================================= +// +// Fullscreen image drawer (move to its own source file!) +// +//============================================================================= + +void ImageScreen::Drawer() +{ + if (mDesc->type == 0) + { + auto tileindexp = NameToTileIndex.CheckKey(FName(mDesc->text, true)); + int tileindex; + if (tileindexp == nullptr) + { + // If this isn't a name, try a literal tile index; + auto c = mDesc->text.GetChars(); + if (*c == '#') tileindex = (int)strtoll(c + 1, nullptr, 0); + // Error out if the screen cannot be found, this is always a definition error that needs to be reported. + else I_Error("Invalid menu screen '%s'", mDesc->text.GetChars()); + } + else tileindex = *tileindexp; + if (!gi->DrawSpecialScreen(origin, tileindex)) // allows the front end to do custom handling for a given image. + { + rotatesprite_fs(int(origin.X * 65536) + (160 << 16), int(origin.Y * 65536) + (100 << 16), 65536L, 0, tileindex, 0, 0, 10 + 64); + } + } + else if (mDesc->type > 0) + { + gi->DrawCenteredTextScreen(origin, mDesc->text, mDesc->type); + } + // QAVs are handled in the Blood frontend. Maybe they should be moved out? Stuff for later, but this is a feature where it is feasible. +} + +ImageScreen* DImageScrollerMenu::newImageScreen(FImageScrollerDescriptor::ScrollerItem* desc) +{ + return new ImageScreen(desc); +} + +void DImageScrollerMenu::Init(DMenu* parent, FImageScrollerDescriptor* desc) +{ + mParentMenu = parent; + index = 0; + mDesc = desc; + canAnimate = !!(mDesc->mFlags & LMF_Animate); + + mCurrent = newImageScreen(&mDesc->mItems[0]); + mCurrent->canAnimate = canAnimate; +} + +bool DImageScrollerMenu::MenuEvent(int mkey, bool fromcontroller) +{ + switch (mkey) + { + case MKEY_Back: + // Before going back the currently running transition must be terminated. + pageTransition.previous = nullptr; + if (pageTransition.current) pageTransition.current->origin = { 0,0 }; + return DMenu::MenuEvent(mkey, fromcontroller); + + + case MKEY_Left: + if (pageTransition.previous == nullptr) + { + if (--index < 0) index = mDesc->mItems.Size() - 1; + auto next = newImageScreen(&mDesc->mItems[index]); + next->canAnimate = canAnimate; + if (!pageTransition.StartTransition(mCurrent, next, MA_Return)) + { + delete mCurrent; + } + mCurrent = next; + //gi->MenuSound(GameInterface::ChooseSound); + } + return true; + + case MKEY_Right: + case MKEY_Enter: + if (pageTransition.previous == nullptr) + { + if (++index >= (int)mDesc->mItems.Size()) index = 0; + auto next = newImageScreen(&mDesc->mItems[index]); + next->canAnimate = canAnimate; + if (!pageTransition.StartTransition(mCurrent, next, MA_Advance)) + { + delete mCurrent; + } + mCurrent = next; + //gi->MenuSound(GameInterface::ChooseSound); + } + return true; + + default: + return DMenu::MenuEvent(mkey, fromcontroller); + } +} + +bool DImageScrollerMenu::MouseEvent(int type, int x, int y) +{ + // Todo: Implement some form of drag event to switch between pages. + return DMenu::MouseEvent(type, x, y); +} + +void DImageScrollerMenu::Ticker() +{ +} + +void DImageScrollerMenu::Drawer() +{ + if (pageTransition.previous != nullptr) + { + auto res = pageTransition.Draw(); + if (res) return; + delete pageTransition.previous; + pageTransition.previous = nullptr; + } + mCurrent->origin = origin; + mCurrent->Drawer(); + mCurrent->origin = {}; +} + diff --git a/source/common/menu/joystickmenu.cpp b/source/common/menu/joystickmenu.cpp new file mode 100644 index 000000000..18a1e5af6 --- /dev/null +++ b/source/common/menu/joystickmenu.cpp @@ -0,0 +1,428 @@ +/* +** joystickmenu.cpp +** The joystick configuration menus +** +**--------------------------------------------------------------------------- +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include + +#include "menu.h" +#include "c_dispatch.h" +#include "filesystem.h" +#include "sc_man.h" +#include "v_font.h" +#include "c_bind.h" +#include "d_event.h" +#include "d_gui.h" + +#define NO_IMP +#include "optionmenuitems.h" + +#if 0 // This requires the entire ZDoom backend to work. + +static TArray Joysticks; +IJoystickConfig *SELECTED_JOYSTICK; + +FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy); + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuSliderJoySensitivity : public FOptionMenuSliderBase +{ +public: + FOptionMenuSliderJoySensitivity(const char *label, double min, double max, double step, int showval) + : FOptionMenuSliderBase(label, min, max, step, showval) + { + } + + double GetSliderValue() + { + return SELECTED_JOYSTICK->GetSensitivity(); + } + + void SetSliderValue(double val) + { + SELECTED_JOYSTICK->SetSensitivity(float(val)); + } +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuSliderJoyScale : public FOptionMenuSliderBase +{ + int mAxis; + int mNeg; + +public: + FOptionMenuSliderJoyScale(const char *label, int axis, double min, double max, double step, int showval) + : FOptionMenuSliderBase(label, min, max, step, showval) + { + mAxis = axis; + mNeg = 1; + } + + double GetSliderValue() + { + double d = SELECTED_JOYSTICK->GetAxisScale(mAxis); + mNeg = d < 0? -1:1; + return d; + } + + void SetSliderValue(double val) + { + SELECTED_JOYSTICK->SetAxisScale(mAxis, float(val * mNeg)); + } +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuSliderJoyDeadZone : public FOptionMenuSliderBase +{ + int mAxis; + int mNeg; + +public: + FOptionMenuSliderJoyDeadZone(const char *label, int axis, double min, double max, double step, int showval) + : FOptionMenuSliderBase(label, min, max, step, showval) + { + mAxis = axis; + mNeg = 1; + } + + double GetSliderValue() + { + double d = SELECTED_JOYSTICK->GetAxisDeadZone(mAxis); + mNeg = d < 0? -1:1; + return d; + } + + void SetSliderValue(double val) + { + SELECTED_JOYSTICK->SetAxisDeadZone(mAxis, float(val * mNeg)); + } +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuItemJoyMap : public FOptionMenuItemOptionBase +{ + int mAxis; +public: + + FOptionMenuItemJoyMap(const char *label, int axis, const char *values, int center) + : FOptionMenuItemOptionBase(label, "none", values, NULL, center) + { + mAxis = axis; + } + + int GetSelection() + { + double f = SELECTED_JOYSTICK->GetAxisMap(mAxis); + FOptionValues **opt = OptionValues.CheckKey(mValues); + if (opt != NULL && *opt != NULL) + { + // Map from joystick axis to menu selection. + for(unsigned i = 0; i < (*opt)->mValues.Size(); i++) + { + if (fabs(f - (*opt)->mValues[i].Value) < FLT_EPSILON) + { + return i; + } + } + } + return -1; + } + + void SetSelection(int selection) + { + FOptionValues **opt = OptionValues.CheckKey(mValues); + // Map from menu selection to joystick axis. + if (opt == NULL || *opt == NULL || (unsigned)selection >= (*opt)->mValues.Size()) + { + selection = JOYAXIS_None; + } + else + { + selection = (int)(*opt)->mValues[selection].Value; + } + SELECTED_JOYSTICK->SetAxisMap(mAxis, (EJoyAxis)selection); + } +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuItemInverter : public FOptionMenuItemOptionBase +{ + int mAxis; +public: + + FOptionMenuItemInverter(const char *label, int axis, int center) + : FOptionMenuItemOptionBase(label, "none", "YesNo", NULL, center) + { + mAxis = axis; + } + + int GetSelection() + { + float f = SELECTED_JOYSTICK->GetAxisScale(mAxis); + return f > 0? 0:1; + } + + void SetSelection(int Selection) + { + float f = fabs(SELECTED_JOYSTICK->GetAxisScale(mAxis)); + if (Selection) f*=-1; + SELECTED_JOYSTICK->SetAxisScale(mAxis, f); + } +}; + +class DJoystickConfigMenu : public DOptionMenu +{ +}; + + +//============================================================================= +// +// Executes a CCMD, action is a CCMD name +// +//============================================================================= + +class FOptionMenuItemJoyConfigMenu : public FOptionMenuItemSubmenu +{ + IJoystickConfig *mJoy; +public: + FOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy) + : FOptionMenuItemSubmenu(label, "JoystickConfigMenu") + { + mJoy = joy; + } + + bool Activate() + { + UpdateJoystickConfigMenu(mJoy); + return FOptionMenuItemSubmenu::Activate(); + } +}; + + +/*======================================= + * + * Joystick Menu + * + *=======================================*/ + +FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy) +{ + FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_JoystickConfigMenu); + if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu) + { + FOptionMenuDescriptor *opt = (FOptionMenuDescriptor *)*desc; + FOptionMenuItem *it; + for(unsigned i=0;imItems.Size();i++) + { + delete opt->mItems[i]; + opt->mItems.Clear(); + } + if (joy == NULL) + { + opt->mTitle = "Configure Controller"; + it = new FOptionMenuItemStaticText("Invalid controller specified for menu", false); + opt->mItems.Push(it); + } + else + { + opt->mTitle.Format("Configure %s", joy->GetName().GetChars()); + + SELECTED_JOYSTICK = joy; + + it = new FOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3); + opt->mItems.Push(it); + it = new FOptionMenuItemStaticText(" ", false); + opt->mItems.Push(it); + + if (joy->GetNumAxes() > 0) + { + it = new FOptionMenuItemStaticText("Axis Configuration", true); + opt->mItems.Push(it); + + for (int i = 0; i < joy->GetNumAxes(); ++i) + { + it = new FOptionMenuItemStaticText(" ", false); + opt->mItems.Push(it); + + it = new FOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false); + opt->mItems.Push(it); + it = new FOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3); + opt->mItems.Push(it); + it = new FOptionMenuItemInverter("Invert", i, false); + opt->mItems.Push(it); + it = new FOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3); + opt->mItems.Push(it); + } + } + else + { + it = new FOptionMenuItemStaticText("No configurable axes", false); + opt->mItems.Push(it); + } + } + opt->mScrollPos = 0; + opt->mSelectedItem = -1; + opt->mIndent = 0; + opt->mPosition = -25; + opt->CalcIndent(); + return opt; + } + return NULL; +} + + + +void UpdateJoystickMenu(IJoystickConfig *selected) +{ + FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_JoystickOptions); + if (desc != NULL && (*desc)->mType == MDESC_OptionsMenu) + { + FOptionMenuDescriptor *opt = (FOptionMenuDescriptor *)*desc; + FOptionMenuItem *it; + for(unsigned i=0;imItems.Size();i++) + { + delete opt->mItems[i]; + } + opt->mItems.Clear(); + + int i; + int itemnum = -1; + + I_GetJoysticks(Joysticks); + if ((unsigned)itemnum >= Joysticks.Size()) + { + itemnum = Joysticks.Size() - 1; + } + if (selected != NULL) + { + for (i = 0; (unsigned)i < Joysticks.Size(); ++i) + { + if (Joysticks[i] == selected) + { + itemnum = i; + break; + } + } + } + + // Todo: Block joystick for changing this one. + it = new FOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false); + opt->mItems.Push(it); + #ifdef _WIN32 + it = new FOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false); + opt->mItems.Push(it); + it = new FOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false); + opt->mItems.Push(it); + it = new FOptionMenuItemOption("Enable raw PlayStation 2 adapters", "joy_ps2raw", "YesNo", NULL, false); + opt->mItems.Push(it); + #endif + + it = new FOptionMenuItemStaticText(" ", false); + opt->mItems.Push(it); + + if (Joysticks.Size() == 0) + { + it = new FOptionMenuItemStaticText("No controllers detected", false); + opt->mItems.Push(it); + if (!use_joystick) + { + it = new FOptionMenuItemStaticText("Controller support must be", false); + opt->mItems.Push(it); + it = new FOptionMenuItemStaticText("enabled to detect any", false); + opt->mItems.Push(it); + } + } + else + { + it = new FOptionMenuItemStaticText("Configure controllers:", false); + opt->mItems.Push(it); + + for (int i = 0; i < (int)Joysticks.Size(); ++i) + { + it = new FOptionMenuItemJoyConfigMenu(Joysticks[i]->GetName(), Joysticks[i]); + opt->mItems.Push(it); + if (i == itemnum) opt->mSelectedItem = opt->mItems.Size(); + } + } + if (opt->mSelectedItem >= (int)opt->mItems.Size()) + { + opt->mSelectedItem = opt->mItems.Size() - 1; + } + + opt->CalcIndent(); + + // If the joystick config menu is open, close it if the device it's + // open for is gone. + for (i = 0; (unsigned)i < Joysticks.Size(); ++i) + { + if (Joysticks[i] == SELECTED_JOYSTICK) + { + break; + } + } + if (i == (int)Joysticks.Size()) + { + SELECTED_JOYSTICK = NULL; + if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DJoystickConfigMenu))) + { + DMenu::CurrentMenu->Close(); + } + } + } +} + +#endif \ No newline at end of file diff --git a/source/common/menu/listmenu.cpp b/source/common/menu/listmenu.cpp new file mode 100644 index 000000000..f9d2562b7 --- /dev/null +++ b/source/common/menu/listmenu.cpp @@ -0,0 +1,651 @@ +/* +** listmenu.cpp +** A simple menu consisting of a list of items +** +**--------------------------------------------------------------------------- +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "v_font.h" +#include "cmdlib.h" +#include "gstrings.h" +#include "d_gui.h" +#include "d_event.h" +#include "menu.h" +#include "v_draw.h" +#include "baselayer.h" +#include "gamecontrol.h" +#include "build.h" + +//============================================================================= +// +// +// +//============================================================================= + +DListMenu::DListMenu(DMenu *parent, FListMenuDescriptor *desc) +: DMenu(parent) +{ + mDesc = NULL; + if (desc != NULL) Init(parent, desc); +} + +//============================================================================= +// +// +// +//============================================================================= + +void DListMenu::Init(DMenu *parent, FListMenuDescriptor *desc) +{ + mParentMenu = parent; + mDesc = desc; + canAnimate = !!(mDesc->mFlags & LMF_Animate); + if (mDesc->mScriptId >= 0) scriptID = mDesc->mScriptId; +#if 0 + if (desc->mCenter) + { + int center = 160; + for(unsigned i=0;imItems.Size(); i++) + { + int xpos = mDesc->mItems[i]->GetX(); + int width = mDesc->mItems[i]->GetWidth(); + int curx = mDesc->mSelectOfsX; + + if (width > 0 && mDesc->mItems[i]->Selectable()) + { + int left = 160 - (width - curx) / 2 - curx; + if (left < center) center = left; + } + } + for(unsigned i=0;imItems.Size(); i++) + { + int width = mDesc->mItems[i]->GetWidth(); + + if (width > 0) + { + mDesc->mItems[i]->SetX(center); + } + } + } +#endif +} + +//============================================================================= +// +// +// +//============================================================================= + +FListMenuItem *DListMenu::GetItem(FName name) +{ + for(unsigned i=0;imItems.Size(); i++) + { + FName nm = mDesc->mItems[i]->GetAction(NULL); + if (nm == name) return mDesc->mItems[i]; + } + return NULL; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DListMenu::Responder (event_t *ev) +{ + if (ev->type == EV_GUI_Event) + { + if (ev->subtype == EV_GUI_KeyDown) + { + int ch = tolower (ev->data1); + + for(unsigned i = mDesc->mSelectedItem + 1; i < mDesc->mItems.Size(); i++) + { + if (mDesc->mItems[i]->CheckHotkey(ch)) + { + mDesc->mSelectedItem = i; + SelectionChanged(); + M_MenuSound(CursorSound); + return true; + } + } + for(int i = 0; i < mDesc->mSelectedItem; i++) + { + if (mDesc->mItems[i]->CheckHotkey(ch)) + { + mDesc->mSelectedItem = i; + SelectionChanged(); + M_MenuSound(CursorSound); + return true; + } + } + } + } + return Super::Responder(ev); +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DListMenu::MenuEvent (int mkey, bool fromcontroller) +{ + int startedAt = mDesc->mSelectedItem; + + switch (mkey) + { + case MKEY_Up: + do + { + if (--mDesc->mSelectedItem < 0) mDesc->mSelectedItem = mDesc->mItems.Size()-1; + } + while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt); + SelectionChanged(); + M_MenuSound(CursorSound); + return true; + + case MKEY_Down: + do + { + if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) mDesc->mSelectedItem = 0; + } + while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt); + SelectionChanged(); + M_MenuSound(CursorSound); + return true; + + case MKEY_Enter: + if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate(mDesc->mMenuName)) + { + M_MenuSound(AdvanceSound); + } + return true; + + default: + return Super::MenuEvent(mkey, fromcontroller); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DListMenu::MouseEvent(int type, int xx, int yy) +{ + int sel = -1; + + // convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture + //x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160; + //y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100; + + + int width43 = (screen->GetHeight() * 4 / 3); + int x = (xx - (screen->GetWidth() - width43) / 2) * 320 / width43; + int y = yy * 200 / screen->GetHeight(); + + if (mFocusControl != NULL) + { + mFocusControl->MouseEvent(type, x, y); + return true; + } + else + { + if ((mDesc->mWLeft <= 0 || x > mDesc->mWLeft) && + (mDesc->mWRight <= 0 || x < mDesc->mWRight)) + { + for(unsigned i=0;imItems.Size(); i++) + { + if (mDesc->mItems[i]->CheckCoordinate(x, y)) + { + if ((int)i != mDesc->mSelectedItem) + { + // no sound. This is too noisy. + } + mDesc->mSelectedItem = i; + SelectionChanged(); + mDesc->mItems[i]->MouseEvent(type, x, y); + return true; + } + } + } + } + mDesc->mSelectedItem = -1; + return Super::MouseEvent(type, x, y); +} + +//============================================================================= +// +// +// +//============================================================================= + +void DListMenu::Ticker () +{ + Super::Ticker(); + for(unsigned i=0;imItems.Size(); i++) + { + mDesc->mItems[i]->Ticker(); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +void DListMenu::PreDraw() +{ + if (mDesc->mCaption.IsNotEmpty()) + { + gi->DrawMenuCaption(origin, GStrings.localize(mDesc->mCaption)); + } +} + +void DListMenu::Drawer () +{ + PreDraw(); + for(unsigned i=0;imItems.Size(); i++) + { + mDesc->mItems[i]->Drawer(this, origin, mDesc->mSelectedItem == (int)i); + } + if (mDesc->mSelectedItem >= 0 && mDesc->mSelectedItem < (int)mDesc->mItems.Size()) + mDesc->mItems[mDesc->mSelectedItem]->DrawSelector(mDesc->mSelectOfsX, mDesc->mSelectOfsY, mDesc->mSelector); + PostDraw(); + Super::Drawer(); +} + +//============================================================================= +// +// base class for menu items +// +//============================================================================= + +FListMenuItem::~FListMenuItem() +{ +} + +bool FListMenuItem::CheckCoordinate(int x, int y) +{ + return false; +} + +void FListMenuItem::Ticker() +{ +} + +void FListMenuItem::Drawer(DListMenu* menu, const DVector2& origin, bool selected) +{ +} + +bool FListMenuItem::Selectable() +{ + return false; +} + +void FListMenuItem::DrawSelector(int xofs, int yofs, FTexture *tex) +{ + if (!tex) + { + if ((DMenu::MenuTime%8) < 6) + { + DrawText(&twod, ConFont, OptionSettings.mFontColorSelection, + (mXpos + xofs - 160) * CleanXfac + screen->GetWidth() / 2, + (mYpos + yofs - 100) * CleanYfac + screen->GetHeight() / 2, + "\xd", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac, + TAG_DONE); + } + } + else + { + DrawTexture (&twod, tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE); + } +} + +bool FListMenuItem::Activate(FName) +{ + return false; // cannot be activated +} + +FName FListMenuItem::GetAction(int *pparam) +{ + return mAction; +} + +bool FListMenuItem::SetString(int i, const char *s) +{ + return false; +} + +bool FListMenuItem::GetString(int i, char *s, int len) +{ + return false; +} + +bool FListMenuItem::SetValue(int i, int value) +{ + return false; +} + +bool FListMenuItem::GetValue(int i, int *pvalue) +{ + return false; +} + +void FListMenuItem::Enable(bool on) +{ + mEnabled = on; +} + +bool FListMenuItem::MenuEvent(int mkey, bool fromcontroller) +{ + return false; +} + +bool FListMenuItem::MouseEvent(int type, int x, int y) +{ + return false; +} + +bool FListMenuItem::CheckHotkey(int c) +{ + return false; +} + +int FListMenuItem::GetWidth() +{ + return 0; +} + + +//============================================================================= +// +// static patch +// +//============================================================================= + +FListMenuItemStaticPatch::FListMenuItemStaticPatch(int x, int y, FTexture *patch, bool centered) +: FListMenuItem(x, y) +{ + mTexture = patch; + mCentered = centered; +} + +void FListMenuItemStaticPatch::Drawer(DListMenu* menu, const DVector2& origin, bool selected) +{ + if (!mTexture) + { + return; + } + + int x = mXpos; + FTexture *tex = mTexture; + if (mYpos >= 0) + { + if (mCentered) x -= tex->GetWidth()/2; + DrawTexture (&twod, tex, x, mYpos, DTA_Clean, true, TAG_DONE); + } + else + { + int x = (mXpos - 160) * CleanXfac + (screen->GetWidth()>>1); + if (mCentered) x -= (tex->GetWidth()*CleanXfac)/2; + DrawTexture (&twod, tex, x, -mYpos*CleanYfac, DTA_CleanNoMove, true, TAG_DONE); + } +} + +//============================================================================= +// +// static text +// +//============================================================================= + +FListMenuItemStaticText::FListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered) +: FListMenuItem(x, y) +{ + mText = text; + mFont = font; + mColor = color; + mCentered = centered; +} + +void FListMenuItemStaticText::Drawer(DListMenu* menu, const DVector2& origin, bool selected) +{ + const char *text = mText; + if (text != NULL) + { + if (mYpos >= 0) + { + int x = mXpos; + if (mCentered) x -= mFont->StringWidth(text)/2; + DrawText(&twod, mFont, mColor, x, mYpos, text, DTA_Clean, true, TAG_DONE); + } + else + { + int x = (mXpos - 160) * CleanXfac + (screen->GetWidth()>>1); + if (mCentered) x -= (mFont->StringWidth(text)*CleanXfac)/2; + DrawText (&twod, mFont, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true, TAG_DONE); + } + } +} + +FListMenuItemStaticText::~FListMenuItemStaticText() +{ + if (mText != NULL) delete [] mText; +} + +//============================================================================= +// +// native static text item +// +//============================================================================= + +FListMenuItemNativeStaticText::FListMenuItemNativeStaticText(int x, int y, const FString& text, int fontnum, int palnum, bool centered) + : FListMenuItem(x, y) +{ + mText = text; + mFontnum = fontnum; + mPalnum = palnum; + mCentered = centered; +} + +void FListMenuItemNativeStaticText::Drawer(DListMenu* menu, const DVector2& origin, bool selected) +{ + const char* text = mText; + if (mText.Len() && !mHidden) + { + gi->DrawNativeMenuText(mFontnum, mPalnum, origin.X + mXpos, origin.Y + mYpos, 1.f, GStrings.localize(text), menu->Descriptor()->mFlags); + } +} + +//============================================================================= +// +// base class for selectable items +// +//============================================================================= + +FListMenuItemSelectable::FListMenuItemSelectable(int x, int y, int height, FName action, int param) +: FListMenuItem(x, y, action) +{ + mHeight = height; + mParam = param; + mHotkey = 0; +} + +bool FListMenuItemSelectable::CheckCoordinate(int x, int y) +{ + return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here +} + +bool FListMenuItemSelectable::Selectable() +{ + return mEnabled && !mHidden; +} + +bool FListMenuItemSelectable::Activate(FName caller) +{ + return M_SetMenu(mAction, mParam, caller); +} + +FName FListMenuItemSelectable::GetAction(int *pparam) +{ + if (pparam != NULL) *pparam = mParam; + return mAction; +} + +bool FListMenuItemSelectable::CheckHotkey(int c) +{ + return c == tolower(mHotkey); +} + +bool FListMenuItemSelectable::MouseEvent(int type, int x, int y) +{ + if (type == DMenu::MOUSE_Release) + { + if (NULL != DMenu::CurrentMenu && DMenu::CurrentMenu->MenuEvent(MKEY_Enter, true)) + { + return true; + } + } + return false; +} + +//============================================================================= +// +// text item +// +//============================================================================= + +FListMenuItemText::FListMenuItemText(int x, int y, int height, int hotkey, const FString &text, FFont *font, EColorRange color, EColorRange color2, FName child, int param) +: FListMenuItemSelectable(x, y, height, child, param) +{ + mText = text; + /* + mFont = font; + mColor = color; + mColorSelected = color2; + */ + mFont = NewSmallFont; + mColor = CR_RED; + mColorSelected = CR_GOLD; + mHotkey = hotkey; +} + +FListMenuItemText::~FListMenuItemText() +{ +} + +void FListMenuItemText::Drawer(DListMenu* menu, const DVector2& origin, bool selected) +{ + const char *text = mText; + if (mText.Len()) + { + DrawText(&twod, mFont, selected ? mColorSelected : mColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE); + } +} + +int FListMenuItemText::GetWidth() +{ + const char *text = mText; + if (mText.Len()) + { + return mFont->StringWidth(GStrings.localize(text)); + } + return 1; +} + + +//============================================================================= +// +// native text item +// +//============================================================================= + +FListMenuItemNativeText::FListMenuItemNativeText(int x, int y, int height, int hotkey, const FString& text, int fontnum, int palnum, float fontscale, FName child, int param) + : FListMenuItemSelectable(x, y, height, child, param) +{ + mText = text; + mFontnum = NIT_BigFont; + mPalnum = NIT_ActiveColor; + mFontscale = fontscale; + mHotkey = hotkey; +} + +FListMenuItemNativeText::~FListMenuItemNativeText() +{ +} + +void FListMenuItemNativeText::Drawer(DListMenu* menu, const DVector2& origin, bool selected) +{ + const char* text = mText; + if (mText.Len() && !mHidden) + { + auto state = selected ? NIT_SelectedState : mEnabled ? NIT_ActiveState : NIT_InactiveState; + gi->DrawNativeMenuText(mFontnum, state, origin.X + mXpos, origin.Y + mYpos, 1.f, GStrings.localize(text), menu->Descriptor()->mFlags); + } +} + +int FListMenuItemNativeText::GetWidth() +{ + return 1; +} + + +//============================================================================= +// +// patch item +// +//============================================================================= + +FListMenuItemPatch::FListMenuItemPatch(int x, int y, int height, int hotkey, FTexture *patch, FName child, int param) +: FListMenuItemSelectable(x, y, height, child, param) +{ + mHotkey = hotkey; + mTexture = patch; +} + +void FListMenuItemPatch::Drawer(DListMenu* menu, const DVector2& origin, bool selected) +{ + DrawTexture (&twod, mTexture, mXpos, mYpos, DTA_Clean, true, TAG_DONE); +} + +int FListMenuItemPatch::GetWidth() +{ + return mTexture + ? mTexture->GetWidth() + : 0; +} + diff --git a/source/common/menu/loadsavemenu.cpp b/source/common/menu/loadsavemenu.cpp new file mode 100644 index 000000000..590085281 --- /dev/null +++ b/source/common/menu/loadsavemenu.cpp @@ -0,0 +1,644 @@ +/* +** loadsavemenu.cpp +** The load game and save game menus +** +**--------------------------------------------------------------------------- +** Copyright 2001-2010 Randy Heit +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "menu/menu.h" +#include "version.h" +#include "m_png.h" +#include "filesystem.h" +#include "v_text.h" +#include "d_event.h" +#include "gstrings.h" +#include "d_gui.h" +#include "v_draw.h" +#include "files.h" +#include "resourcefile.h" +#include "sjson.h" +#include "savegamehelp.h" +#include "i_specialpaths.h" +#include "../../platform/win32/i_findfile.h" // This is a temporary direct path. Needs to be fixed when stuff gets cleaned up. + + + +class DLoadSaveMenu : public DListMenu +{ + using Super = DListMenu; + +protected: + + int Selected = 0; + int TopItem = 0; + + + int savepicLeft; + int savepicTop; + int savepicWidth; + int savepicHeight; + + int rowHeight; + int listboxLeft; + int listboxTop; + int listboxWidth; + + int listboxRows; + int listboxHeight; + int listboxRight; + int listboxBottom; + + int commentLeft; + int commentTop; + int commentWidth; + int commentHeight; + int commentRight; + int commentBottom; + int commentRows; + + double FontScale; + DTextEnterMenu *mInput = nullptr; + TArray BrokenSaveComment; + bool mEntering = false; + + + //============================================================================= + // + // End of static savegame maintenance code + // + //============================================================================= + + DLoadSaveMenu() + { + savegameManager.ReadSaveStrings(); + } + + void Init(DMenu* parent, FListMenuDescriptor* desc) + { + Super::Init(parent, desc); + int Width43 = screen->GetHeight() * 4 / 3; + int Left43 = (screen->GetWidth() - Width43) / 2; + float wScale = Width43 / 640.; + savepicLeft = Left43 + int(20 * wScale); + savepicTop = mDesc->mYpos * screen->GetHeight() / 200 ; + savepicWidth = int(240 * wScale); + savepicHeight = int(180 * wScale); + + + FontScale = max(screen->GetHeight() / 480, 1); + rowHeight = std::max(int((NewConsoleFont->GetHeight() + 1) * FontScale), 1); + listboxLeft = savepicLeft + savepicWidth + int(20 * wScale); + listboxTop = savepicTop; + listboxWidth = Width43 + Left43 - listboxLeft - int(30 * wScale); + int listboxHeight1 = screen->GetHeight() - listboxTop - int(20*wScale); + listboxRows = (listboxHeight1 - 1) / rowHeight; + listboxHeight = listboxRows * rowHeight + 1; + listboxRight = listboxLeft + listboxWidth; + listboxBottom = listboxTop + listboxHeight; + + commentLeft = savepicLeft; + commentTop = savepicTop + savepicHeight + int(16 * wScale); + commentWidth = savepicWidth; + commentHeight = listboxHeight - savepicHeight - (16 * wScale); + commentRight = commentLeft + commentWidth; + commentBottom = commentTop + commentHeight; + commentRows = commentHeight / rowHeight; + UpdateSaveComment(); + } + + //============================================================================= + // + // + // + //============================================================================= + + void Drawer() override + { + Super::Drawer(); + + int i; + unsigned j; + bool didSeeSelected = false; + + // Draw picture area + /* + if (gameaction == ga_loadgame || gameaction == ga_loadgamehidecon || gameaction == ga_savegame) + { + return; + } + */ + + PalEntry frameColor(255, 80, 80, 80); // todo: pick a proper color per game. + PalEntry fillColor(160, 0, 0, 0); + DrawFrame(&twod, frameColor, savepicLeft, savepicTop, savepicWidth, savepicHeight, -1); + if (!savegameManager.DrawSavePic(savepicLeft, savepicTop, savepicWidth, savepicHeight)) + { + twod.AddColorOnlyQuad(savepicLeft, savepicTop, savepicWidth, savepicHeight, fillColor); + + if (savegameManager.SavegameCount() > 0) + { + if (Selected >= savegameManager.SavegameCount()) Selected = 0; + FString text = (Selected == -1 || !savegameManager.GetSavegame(Selected)->bOldVersion) ? GStrings("MNU_NOPICTURE") : GStrings("MNU_DIFFVERSION"); + int textlen = NewSmallFont->StringWidth(text) * CleanXfac; + + DrawText(&twod, NewSmallFont, CR_GOLD, savepicLeft + (savepicWidth - textlen) / 2, + savepicTop + (savepicHeight - rowHeight) / 2, text, DTA_CleanNoMove, true, TAG_DONE); + } + } + + // Draw comment area + DrawFrame(&twod, frameColor, commentLeft, commentTop, commentWidth, commentHeight, -1); + twod.AddColorOnlyQuad(commentLeft, commentTop, commentWidth, commentHeight, fillColor); + + int numlinestoprint = std::min(commentRows, (int)BrokenSaveComment.Size()); + for (int i = 0; i < numlinestoprint; i++) + { + DrawText(&twod, NewConsoleFont, CR_ORANGE, commentLeft / FontScale, (commentTop + rowHeight * i) / FontScale, BrokenSaveComment[i].Text, + DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE); + } + + + // Draw file area + DrawFrame(&twod, frameColor, listboxLeft, listboxTop, listboxWidth, listboxHeight, -1); + twod.AddColorOnlyQuad(listboxLeft, listboxTop, listboxWidth, listboxHeight, fillColor); + + if (savegameManager.SavegameCount() == 0) + { + FString text = GStrings("MNU_NOFILES"); + int textlen = int(NewConsoleFont->StringWidth(text) * FontScale); + + DrawText(&twod, NewConsoleFont, CR_GOLD, (listboxLeft + (listboxWidth - textlen) / 2) / FontScale, (listboxTop + (listboxHeight - rowHeight) / 2) / FontScale, text, + DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE); + return; + } + + j = TopItem; + for (i = 0; i < listboxRows && j < savegameManager.SavegameCount(); i++) + { + int colr; + auto& node = *savegameManager.GetSavegame(j); + if (node.bOldVersion) + { + colr = CR_RED; + } + else if (node.bMissingWads) + { + colr = CR_YELLOW; + } + else if (j == Selected) + { + colr = CR_WHITE; + } + else + { + colr = CR_TAN; + } + + //screen->SetClipRect(listboxLeft, listboxTop+rowHeight*i, listboxRight, listboxTop+rowHeight*(i+1)); + + if ((int)j == Selected) + { + twod.AddColorOnlyQuad(listboxLeft, listboxTop + rowHeight * i, listboxWidth, rowHeight, mEntering ? PalEntry(255, 255, 0, 0) : PalEntry(255, 0, 0, 255)); + didSeeSelected = true; + if (!mEntering) + { + DrawText(&twod, NewConsoleFont, colr, (listboxLeft + 1) / FontScale, (listboxTop + rowHeight * i + FontScale) / FontScale, node.SaveTitle, + DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE); + } + else + { + FStringf s("%s%c", mInput->GetText(), NewConsoleFont->GetCursor()); + int length = int(NewConsoleFont->StringWidth(s) * FontScale); + int displacement = std::min(0, listboxWidth - 2 - length); + DrawText(&twod, NewConsoleFont, CR_WHITE, (listboxLeft + 1 + displacement) / FontScale, (listboxTop + rowHeight * i + FontScale) / FontScale, s, + DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE); + } + } + else + { + DrawText(&twod, NewConsoleFont, colr, (listboxLeft + 1) / FontScale, (listboxTop + rowHeight * i + FontScale) / FontScale, node.SaveTitle, + DTA_VirtualWidthF, screen->GetWidth() / FontScale, DTA_VirtualHeightF, screen->GetHeight() / FontScale, DTA_KeepRatio, true, TAG_DONE); + } + //screen->ClearClipRect(); + j++; + } + } + + void UpdateSaveComment() + { + BrokenSaveComment = V_BreakLines(NewConsoleFont, int(commentWidth / FontScale), savegameManager.SaveCommentString); + } + + //============================================================================= + // + // + // + //============================================================================= + + bool MenuEvent(int mkey, bool fromcontroller) override + { + auto& manager = savegameManager; + switch (mkey) + { + case MKEY_Up: + if (manager.SavegameCount() > 1) + { + if (Selected == -1) Selected = TopItem; + else + { + if (--Selected < 0) Selected = manager.SavegameCount() - 1; + if (Selected < TopItem) TopItem = Selected; + else if (Selected >= TopItem + listboxRows) TopItem = std::max(0, Selected - listboxRows + 1); + } + manager.UnloadSaveData(); + manager.ExtractSaveData(Selected); + UpdateSaveComment(); + } + return true; + + case MKEY_Down: + if (manager.SavegameCount() > 1) + { + if (Selected == -1) Selected = TopItem; + else + { + if (++Selected >= manager.SavegameCount()) Selected = 0; + if (Selected < TopItem) TopItem = Selected; + else if (Selected >= TopItem + listboxRows) TopItem = std::max(0, Selected - listboxRows + 1); + } + manager.UnloadSaveData(); + manager.ExtractSaveData(Selected); + UpdateSaveComment(); + } + return true; + + case MKEY_PageDown: + if (manager.SavegameCount() > 1) + { + if (TopItem >= manager.SavegameCount() - listboxRows) + { + TopItem = 0; + if (Selected != -1) Selected = 0; + } + else + { + TopItem = std::min(TopItem + listboxRows, int(manager.SavegameCount()) - listboxRows); + if (TopItem > Selected&& Selected != -1) Selected = TopItem; + } + manager.UnloadSaveData(); + manager.ExtractSaveData(Selected); + UpdateSaveComment(); + } + return true; + + case MKEY_PageUp: + if (manager.SavegameCount() > 1) + { + if (TopItem == 0) + { + TopItem = std::max(0, int(manager.SavegameCount()) - listboxRows); + if (Selected != -1) Selected = TopItem; + } + else + { + TopItem = std::max(int(TopItem - listboxRows), 0); + if (Selected >= TopItem + listboxRows) Selected = TopItem; + } + manager.UnloadSaveData(); + manager.ExtractSaveData(Selected); + UpdateSaveComment(); + } + return true; + + case MKEY_Enter: + return false; // This event will be handled by the subclasses + + case MKEY_MBYes: + { + if (Selected < manager.SavegameCount()) + { + Selected = manager.RemoveSaveSlot(Selected); + UpdateSaveComment(); + } + return true; + } + + default: + return Super::MenuEvent(mkey, fromcontroller); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + bool MouseEvent(int type, int x, int y) override + { + auto& manager = savegameManager; + if (x >= listboxLeft && x < listboxLeft + listboxWidth && + y >= listboxTop && y < listboxTop + listboxHeight) + { + int lineno = (y - listboxTop) / rowHeight; + + if (TopItem + lineno < manager.SavegameCount()) + { + Selected = TopItem + lineno; + manager.UnloadSaveData(); + manager.ExtractSaveData(Selected); + UpdateSaveComment(); + if (type == MOUSE_Release) + { + if (MenuEvent(MKEY_Enter, true)) + { + return true; + } + } + } + else Selected = -1; + } + else Selected = -1; + + return Super::MouseEvent(type, x, y); + } + + //============================================================================= + // + // + // + //============================================================================= + + bool Responder(event_t * ev) override + { + auto& manager = savegameManager; + if (ev->type == EV_GUI_Event) + { + if (ev->subtype == EV_GUI_KeyDown) + { + if ((unsigned)Selected < manager.SavegameCount()) + { + switch (ev->data1) + { + case GK_F1: + manager.SetFileInfo(Selected); + UpdateSaveComment(); + return true; + + case GK_DEL: + case '\b': + { + FString EndString; + EndString.Format("%s" TEXTCOLOR_WHITE "%s" TEXTCOLOR_NORMAL "?\n\n%s", + GStrings("MNU_DELETESG"), manager.GetSavegame(Selected)->SaveTitle.GetChars(), GStrings("PRESSYN")); + M_StartMessage(EndString, 0, -1); + } + return true; + } + } + } + else if (ev->subtype == EV_GUI_WheelUp) + { + if (TopItem > 0) TopItem--; + return true; + } + else if (ev->subtype == EV_GUI_WheelDown) + { + if (TopItem < manager.SavegameCount() - listboxRows) TopItem++; + return true; + } + } + return Super::Responder(ev); + } +}; + +//============================================================================= +// +// +// +//============================================================================= + +class DSaveMenu : public DLoadSaveMenu +{ + using Super = DLoadSaveMenu; + FString mSaveName; +public: + + + //============================================================================= + // + // + // + //============================================================================= + + DSaveMenu() + { + savegameManager.InsertNewSaveNode(); + TopItem = 0; + Selected = savegameManager.ExtractSaveData (-1); + UpdateSaveComment(); + } + + //============================================================================= + // + // + // + //============================================================================= + + void Destroy() override + { + if (savegameManager.RemoveNewSaveNode()) + { + Selected--; + } + Super::Destroy(); + } + //============================================================================= + // + // + // + //============================================================================= + + bool MenuEvent (int mkey, bool fromcontroller) override + { + if (Super::MenuEvent(mkey, fromcontroller)) + { + return true; + } + if (Selected == -1) + { + return false; + } + + if (mkey == MKEY_Enter) + { + FString SavegameString = (Selected != 0)? savegameManager.GetSavegame(Selected)->SaveTitle : FString(); + mInput = new DTextEnterMenu(this, NewConsoleFont, SavegameString, listboxWidth, false, false); + M_ActivateMenu(mInput); + mEntering = true; + } + else if (mkey == MKEY_Input) + { + mEntering = false; + mSaveName = mInput->GetText(); + mInput = nullptr; + } + else if (mkey == MKEY_Abort) + { + mEntering = false; + mInput = nullptr; + } + return false; + } + + //============================================================================= + // + // + // + //============================================================================= + + bool MouseEvent(int type, int x, int y) override + { + if (mSaveName.Len() > 0) + { + // Do not process events when saving is in progress to avoid update of the current index, + // i.e. Selected member variable must remain unchanged + return true; + } + + return Super::MouseEvent(type, x, y); + } + + //============================================================================= + // + // + // + //============================================================================= + + bool Responder (event_t *ev) override + { + if (ev->subtype == EV_GUI_KeyDown) + { + if (Selected != -1) + { + switch (ev->data1) + { + case GK_DEL: + case '\b': + // cannot delete 'new save game' item + if (Selected == 0) return true; + break; + + case 'N': + Selected = TopItem = 0; + savegameManager.UnloadSaveData(); + return true; + } + } + } + return Super::Responder(ev); + } + + //============================================================================= + // + // + // + //============================================================================= + + void Ticker() override + { + if (mSaveName.Len() > 0) + { + savegameManager.DoSave(Selected, mSaveName); + } + } + +}; + +//============================================================================= +// +// +// +//============================================================================= + +class DLoadMenu : public DLoadSaveMenu +{ + using Super = DLoadSaveMenu; + +public: + + //============================================================================= + // + // + // + //============================================================================= + + DLoadMenu() + { + TopItem = 0; + Selected = savegameManager.ExtractSaveData(-1); + UpdateSaveComment(); + } + + //============================================================================= + // + // + // + //============================================================================= + + bool MenuEvent(int mkey, bool fromcontroller) override + { + if (Super::MenuEvent(mkey, fromcontroller)) + { + return true; + } + if (Selected == -1 || savegameManager.SavegameCount() == 0) + { + return false; + } + + if (mkey == MKEY_Enter) + { + savegameManager.LoadSavegame(Selected); + return true; + } + return false; + } +}; + +static TMenuClassDescriptor _lm("LoadMenu"); +static TMenuClassDescriptor _sm("SaveMenu"); + +void RegisterLoadsaveMenus() +{ + menuClasses.Push(&_sm); + menuClasses.Push(&_lm); +} diff --git a/source/common/menu/menu.cpp b/source/common/menu/menu.cpp new file mode 100644 index 000000000..e1265fd2c --- /dev/null +++ b/source/common/menu/menu.cpp @@ -0,0 +1,1046 @@ +/* +** menu.cpp +** Menu base class and global interface +** +**--------------------------------------------------------------------------- +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "c_dispatch.h" +#include "d_gui.h" +#include "c_console.h" +#include "c_bind.h" +#include "c_cvars.h" +#include "d_event.h" +//#include "i_input.h" +#include "gameconfigfile.h" +#include "gstrings.h" +#include "menu.h" +#include "textures.h" +#include "c_buttons.h" +#include "v_2ddrawer.h" +#include "printf.h" +#include "v_draw.h" +#include "gamecontrol.h" +#include "fx_man.h" +#include "pragmas.h" +#include "build.h" +#include "baselayer.h" +#include "statistics.h" + +void RegisterDukeMenus(); +void RegisterRedneckMenus(); +void RegisterBloodMenus(); +void RegisterSWMenus(); +void RegisterLoadsaveMenus(); +void RegisterOptionMenus(); +extern bool rotatesprite_2doverride; +bool help_disabled, credits_disabled; +int g_currentMenu; // accessible by CON scripts - contains the current menu's script ID if defined or INT_MAX if none given. +int DrawBackground; +TArray toDelete; + +// +// Todo: Move these elsewhere +// +CVAR (Float, mouse_sensitivity, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +EXTERN_CVAR (Bool, show_messages) + + +CVAR(Bool, menu_sounds, true, CVAR_ARCHIVE) // added mainly because RR's sounds are so supremely annoying. +//CVAR (Float, snd_menuvolume, 0.6f, CVAR_ARCHIVE) the current sound engine cannot deal with this. +CVAR(Int, m_use_mouse, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) + +TArray menuClasses(TArray::ENoInit(0)); + +DMenu *DMenu::CurrentMenu; +int DMenu::MenuTime; + +FGameStartup GameStartupInfo; +EMenuState menuactive; +bool M_DemoNoPlay; +FButtonStatus MenuButtons[NUM_MKEYS]; +int MenuButtonTickers[NUM_MKEYS]; +bool MenuButtonOrigin[NUM_MKEYS]; +int BackbuttonTime; +float BackbuttonAlpha; +static bool MenuEnabled = true; + + +#define KEY_REPEAT_DELAY (MENU_TICRATE*5/12) +#define KEY_REPEAT_RATE (3) + + +static MenuTransition transition; + +bool MenuTransition::StartTransition(DMenu *from, DMenu *to, MenuTransitionType animtype) +{ + if (!from->canAnimate || !to->canAnimate || animtype == MA_None) + { + return false; + } + else + { + start = (int32_t) totalclock; + length = 30; + dir = animtype == MA_Advance? 1 : -1; + previous = from; + current = to; + return true; + } +} + +bool MenuTransition::Draw() +{ + if (totalclock < start + length) + { + double factor = 120 * xdim / ydim; + double phase = ((int32_t) totalclock - start) / double(length) * M_PI + M_PI/2; + + previous->origin.X = factor * dir * (sin(phase) - 1.); + current->origin.X = factor * dir * (sin(phase) + 1.); + previous->Drawer(); + current->Drawer(); + return true; + } + return false; +} + +//============================================================================ +// +// DMenu base class +// +//============================================================================ + + +DMenu::DMenu(DMenu *parent) +{ + mParentMenu = parent; + mMouseCapture = false; + mBackbuttonSelected = false; +} + +bool DMenu::Responder (event_t *ev) +{ + bool res = false; + if (ev->type == EV_GUI_Event) + { + if (ev->subtype == EV_GUI_LButtonDown) + { + res = MouseEventBack(MOUSE_Click, ev->data1, ev->data2); + // make the menu's mouse handler believe that the current coordinate is outside the valid range + if (res) ev->data2 = -1; + res |= MouseEvent(MOUSE_Click, ev->data1, ev->data2); + if (res) + { + SetCapture(); + } + + } + else if (ev->subtype == EV_GUI_MouseMove) + { + BackbuttonTime = BACKBUTTON_TIME; + if (mMouseCapture || m_use_mouse == 1) + { + res = MouseEventBack(MOUSE_Move, ev->data1, ev->data2); + if (res) ev->data2 = -1; + res |= MouseEvent(MOUSE_Move, ev->data1, ev->data2); + } + } + else if (ev->subtype == EV_GUI_LButtonUp) + { + if (mMouseCapture) + { + ReleaseCapture(); + res = MouseEventBack(MOUSE_Release, ev->data1, ev->data2); + if (res) ev->data2 = -1; + res |= MouseEvent(MOUSE_Release, ev->data1, ev->data2); + } + } + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DMenu::MenuEvent (int mkey, bool fromcontroller) +{ + switch (mkey) + { + case MKEY_Back: + { + if (scriptID != 0) + { + M_MenuSound(DMenu::CurrentMenu->mParentMenu? BackSound : CloseSound); + Close(); + return true; + } + } + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +void DMenu::Close () +{ + assert(DMenu::CurrentMenu == this); + + DMenu::CurrentMenu = mParentMenu; + if (mParentMenu && transition.StartTransition(this, mParentMenu, MA_Return)) + { + g_currentMenu = DMenu::CurrentMenu->scriptID; + } + else + { + Destroy(); + toDelete.Push(this); + if (DMenu::CurrentMenu == NULL) + { + M_ClearMenus(); + } + else + { + g_currentMenu = DMenu::CurrentMenu->scriptID; + } + } +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DMenu::MouseEvent(int type, int x, int y) +{ + return true; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DMenu::MouseEventBack(int type, int x, int y) +{ + if (m_show_backbutton >= 0) + { + FTexture* tex = TileFiles.GetTexture("demolition/graphics/m_back.png"); + if (tex != NULL) + { + if (m_show_backbutton&1) x -= screen->GetWidth() - tex->GetWidth() * CleanXfac; + if (m_show_backbutton&2) y -= screen->GetHeight() - tex->GetHeight() * CleanYfac; + mBackbuttonSelected = ( x >= 0 && x < tex->GetWidth() * CleanXfac && + y >= 0 && y < tex->GetHeight() * CleanYfac); + if (mBackbuttonSelected && type == MOUSE_Release) + { + if (m_use_mouse == 2) mBackbuttonSelected = false; + MenuEvent(MKEY_Back, true); + } + return mBackbuttonSelected; + } + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +void DMenu::SetCapture() +{ + if (!mMouseCapture) + { + mMouseCapture = true; + I_SetMouseCapture(); + } +} + +void DMenu::ReleaseCapture() +{ + if (mMouseCapture) + { + mMouseCapture = false; + I_ReleaseMouseCapture(); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +void DMenu::Ticker () +{ +} + +void DMenu::Drawer () +{ + if (this == DMenu::CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse) + { + FTexture* tex = TileFiles.GetTexture("demolition/graphics/m_back.png"); + int w = tex->GetWidth() * CleanXfac; + int h = tex->GetHeight() * CleanYfac; + int x = (!(m_show_backbutton&1))? 0:screen->GetWidth() - w; + int y = (!(m_show_backbutton&2))? 0:screen->GetHeight() - h; + if (mBackbuttonSelected && (mMouseCapture || m_use_mouse == 1)) + { + DrawTexture(&twod, tex, x, y, DTA_CleanNoMove, true, DTA_ColorOverlay, MAKEARGB(40, 255,255,255), TAG_DONE); + } + else + { + DrawTexture(&twod, tex, x, y, DTA_CleanNoMove, true, DTA_Alpha, BackbuttonAlpha, TAG_DONE); + } + } +} + + +bool DMenu::DimAllowed() +{ + return true; +} + +bool DMenu::TranslateKeyboardEvents() +{ + return true; +} + +//============================================================================= +// +// +// +//============================================================================= + +void M_StartControlPanel (bool makeSound) +{ + static bool created = false; + // intro might call this repeatedly + if (DMenu::CurrentMenu != NULL) + return; + + if (!created) // Cannot do this earlier. + { + created = true; + M_CreateMenus(); + } + FX_StopAllSounds(); + gi->MenuOpened(); + if (makeSound) gi->MenuSound(ActivateSound); + + buttonMap.ResetButtonStates (); + inputState.ClearAllKeyStatus(); + for (int i = 0; i < NUM_MKEYS; ++i) + { + MenuButtons[i].ReleaseKey(0); + } + + C_HideConsole (); // [RH] Make sure console goes bye bye. + mouseGrabInput(false); + menuactive = MENU_On; + // Pause sound effects before we play the menu switch sound. + // That way, it won't be paused. + //P_CheckTickerPaused (); + + BackbuttonTime = 0; + BackbuttonAlpha = 0; + DrawBackground = -1; + DMenu::MenuTime = -1; + M_Ticker(); // This needs to be called once here to make sure that the menu actually has ticked before it gets drawn for the first time. +} + +void Menu_Open(int playerid) +{ + M_StartControlPanel(DMenu::CurrentMenu == nullptr); +} + +//============================================================================= +// +// +// +//============================================================================= + +void M_ActivateMenu(DMenu *menu) +{ + g_currentMenu = menu->scriptID; + if (menuactive == MENU_Off) menuactive = MENU_On; + if (DMenu::CurrentMenu != NULL) + { + DMenu::CurrentMenu->ReleaseCapture(); + transition.StartTransition(DMenu::CurrentMenu, menu, MA_Advance); + } + DMenu::CurrentMenu = menu; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool M_SetMenu(FName menu, int param, FName caller) +{ + if (DrawBackground == -1) + { + if (menu == NAME_MainMenu) DrawBackground = 1; + else DrawBackground = 0; + } + // some menus need some special treatment (needs to be adjusted for the various frontends. + switch (caller) + { + case NAME_EpisodeMenu: + // sent from the episode menu + GameStartupInfo.Episode = param; + GameStartupInfo.Level = 0; + GameStartupInfo.CustomLevel1 = GameStartupInfo.CustomLevel2 = -1; + GameStartupInfo.Skill = gDefaultSkill; + break; + + case NAME_CustomGameMenu: + GameStartupInfo.CustomLevel1 = param; + GameStartupInfo.CustomLevel2 = -1; + GameStartupInfo.Episode = 0; // Set start to E1L1 so that even if the script fails to set the starting level it is set to something valid. + GameStartupInfo.Level = 0; + GameStartupInfo.Skill = gDefaultSkill; + gi->CustomMenuSelection(param, -1); + break; + + case NAME_CustomSubMenu1: + case NAME_CustomSubMenu2: + case NAME_CustomSubMenu3: + case NAME_CustomSubMenu4: + case NAME_CustomSubMenu5: + case NAME_CustomSubMenu6: + case NAME_CustomSubMenu7: + GameStartupInfo.CustomLevel2 = param; + gi->CustomMenuSelection(GameStartupInfo.CustomLevel1, param); + break; + + case NAME_SkillMenu: + GameStartupInfo.Skill = param; + break; + } + + switch (menu) + { + case NAME_StartGame: + M_ClearMenus(); // must be done before starting the level. + STAT_StartNewGame(gVolumeNames[GameStartupInfo.Episode], GameStartupInfo.Skill); + gi->StartGame(GameStartupInfo); + return false; + + case NAME_CustomSubMenu1: + menu = ENamedName(menu + param); + break; + +#if 0 + case NAME_StartgameConfirm: + { + // sent from the skill menu for a skill that needs to be confirmed + GameStartupInfo.Skill = param; + + const char *msg = AllSkills[param].MustConfirmText; + if (*msg==0) msg = GStrings("NIGHTMARE"); + M_StartMessage (msg, 0, -1, NAME_StartgameConfirmed); + return; + } +#endif + + case NAME_SaveGameMenu: + if (!gi->CanSave()) + { + // cannot save outside the game. + M_StartMessage (GStrings("SAVEDEAD"), 1, -1); + return true; + } + break; + + case NAME_QuitMenu: + // This is no separate class + C_DoCommand("menu_quit"); + return true; + + case NAME_EndgameMenu: + // This is no separate class + C_DoCommand("menu_endgame"); + return true; + } + + // End of special checks + + FMenuDescriptor **desc = MenuDescriptors.CheckKey(menu); + if (desc != NULL) + { + /* + if ((*desc)->mNetgameMessage.IsNotEmpty() && netgame && !demoplayback) + { + M_StartMessage((*desc)->mNetgameMessage, 1); + return; + } + */ + + if ((*desc)->mType == MDESC_ListMenu) + { + FListMenuDescriptor *ld = static_cast(*desc); + if (ld->mAutoselect >= 0 && ld->mAutoselect < (int)ld->mItems.Size()) + { + // recursively activate the autoselected item without ever creating this menu. + ld->mItems[ld->mAutoselect]->Activate(ld->mMenuName); + } + else + { + DListMenu* newmenu; + if (ld->mClass != NAME_None) + { + auto ndx = menuClasses.FindEx([=](const auto p) { return p->mName == ld->mClass; }); + if (ndx == menuClasses.Size()) + { + I_Error("Bad menu class %s\n", ld->mClass.GetChars()); + } + else + { + newmenu = (DListMenu*)menuClasses[ndx]->CreateNew(); + } + } + else + { + newmenu = new DListMenu; + } + newmenu->Init(DMenu::CurrentMenu, ld); + M_ActivateMenu(newmenu); + } + } + else if ((*desc)->mType == MDESC_OptionsMenu) + { + FOptionMenuDescriptor *ld = static_cast(*desc); + DOptionMenu* newmenu; + if (ld->mClass != NAME_None) + { + auto ndx = menuClasses.FindEx([=](const auto p) { return p->mName == ld->mClass; }); + if (ndx == menuClasses.Size()) + { + I_Error("Bad menu class %s\n", ld->mClass.GetChars()); + } + else + { + newmenu = (DOptionMenu*)menuClasses[ndx]->CreateNew(); + } + } + else + { + newmenu = new DOptionMenu; + } + newmenu->Init(DMenu::CurrentMenu, ld); + M_ActivateMenu(newmenu); + } + else if ((*desc)->mType == MDESC_ImageScroller) + { + FImageScrollerDescriptor* ld = static_cast(*desc); + DImageScrollerMenu* newmenu; + if (ld->mClass != NAME_None) + { + auto ndx = menuClasses.FindEx([=](const auto p) { return p->mName == ld->mClass; }); + if (ndx == menuClasses.Size()) + { + I_Error("Bad menu class %s\n", ld->mClass.GetChars()); + } + else + { + newmenu = (DImageScrollerMenu*)menuClasses[ndx]->CreateNew(); + } + } + else + { + newmenu = new DImageScrollerMenu; + } + newmenu->Init(DMenu::CurrentMenu, ld); + M_ActivateMenu(newmenu); + } + return true; + } + else + { + /* + const PClass *menuclass = PClass::FindClass(menu); + if (menuclass != NULL) + { + if (menuclass->IsDescendantOf(RUNTIME_CLASS(DMenu))) + { + DMenu *newmenu = (DMenu*)menuclass->CreateNew(); + newmenu->mParentMenu = DMenu::CurrentMenu; + M_ActivateMenu(newmenu); + return true; + } + } + */ + } + Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars()); + M_ClearMenus(); + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool M_DoResponder (event_t *ev) +{ + int ch = 0; + bool keyup = false; + int mkey = NUM_MKEYS; + bool fromcontroller = true; + + /* + if (chatmodeon) + { + return false; + } + */ + + if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off) + { + // There are a few input sources we are interested in: + // + // EV_KeyDown / EV_KeyUp : joysticks/gamepads/controllers + // EV_GUI_KeyDown / EV_GUI_KeyUp : the keyboard + // EV_GUI_Char : printable characters, which we want in string input mode + // + // This code previously listened for EV_GUI_KeyRepeat to handle repeating + // in the menus, but that doesn't work with gamepads, so now we combine + // the multiple inputs into buttons and handle the repetition manually. + if (ev->type == EV_GUI_Event) + { + fromcontroller = false; + if (ev->subtype == EV_GUI_KeyRepeat) + { + // We do our own key repeat handling but still want to eat the + // OS's repeated keys. + return true; + } + else if (ev->subtype == EV_GUI_BackButtonDown || ev->subtype == EV_GUI_BackButtonUp) + { + mkey = MKEY_Back; + keyup = ev->subtype == EV_GUI_BackButtonUp; + } + else if (ev->subtype != EV_GUI_KeyDown && ev->subtype != EV_GUI_KeyUp) + { + // do we want mouse input? + if (ev->subtype >= EV_GUI_FirstMouseEvent && ev->subtype <= EV_GUI_LastMouseEvent) + { + if (!m_use_mouse) + return true; + } + + // pass everything else on to the current menu + return DMenu::CurrentMenu->Responder(ev); + } + else if (DMenu::CurrentMenu->TranslateKeyboardEvents()) + { + ch = ev->data1; + keyup = ev->subtype == EV_GUI_KeyUp; + switch (ch) + { + case GK_BACK: mkey = MKEY_Back; break; + case GK_ESCAPE: mkey = MKEY_Back; break; + case GK_RETURN: mkey = MKEY_Enter; break; + case GK_UP: mkey = MKEY_Up; break; + case GK_DOWN: mkey = MKEY_Down; break; + case GK_LEFT: mkey = MKEY_Left; break; + case GK_RIGHT: mkey = MKEY_Right; break; + case GK_BACKSPACE: mkey = MKEY_Clear; break; + case GK_PGUP: mkey = MKEY_PageUp; break; + case GK_PGDN: mkey = MKEY_PageDown; break; + default: + if (!keyup) + { + return DMenu::CurrentMenu->Responder(ev); + } + break; + } + } + } + else if (menuactive != MENU_WaitKey && (ev->type == EV_KeyDown || ev->type == EV_KeyUp)) + { + keyup = ev->type == EV_KeyUp; + + ch = ev->data1; + switch (ch) + { + case KEY_JOY1: + case KEY_PAD_A: + mkey = MKEY_Enter; + break; + + case KEY_JOY2: + case KEY_PAD_B: + mkey = MKEY_Back; + break; + + case KEY_JOY3: + case KEY_PAD_X: + mkey = MKEY_Clear; + break; + + case KEY_JOY5: + case KEY_PAD_LSHOULDER: + mkey = MKEY_PageUp; + break; + + case KEY_JOY6: + case KEY_PAD_RSHOULDER: + mkey = MKEY_PageDown; + break; + + case KEY_PAD_DPAD_UP: + case KEY_PAD_LTHUMB_UP: + case KEY_JOYAXIS1MINUS: + case KEY_JOYPOV1_UP: + mkey = MKEY_Up; + break; + + case KEY_PAD_DPAD_DOWN: + case KEY_PAD_LTHUMB_DOWN: + case KEY_JOYAXIS1PLUS: + case KEY_JOYPOV1_DOWN: + mkey = MKEY_Down; + break; + + case KEY_PAD_DPAD_LEFT: + case KEY_PAD_LTHUMB_LEFT: + case KEY_JOYAXIS2MINUS: + case KEY_JOYPOV1_LEFT: + mkey = MKEY_Left; + break; + + case KEY_PAD_DPAD_RIGHT: + case KEY_PAD_LTHUMB_RIGHT: + case KEY_JOYAXIS2PLUS: + case KEY_JOYPOV1_RIGHT: + mkey = MKEY_Right; + break; + } + } + + if (mkey != NUM_MKEYS) + { + if (keyup) + { + MenuButtons[mkey].ReleaseKey(ch); + return false; + } + else + { + MenuButtons[mkey].PressKey(ch); + MenuButtonOrigin[mkey] = fromcontroller; + if (mkey <= MKEY_PageDown) + { + MenuButtonTickers[mkey] = KEY_REPEAT_DELAY; + } + DMenu::CurrentMenu->MenuEvent(mkey, fromcontroller); + return true; + } + } + return DMenu::CurrentMenu->Responder(ev) || !keyup; + } + else if (MenuEnabled) + { + if (ev->type == EV_KeyDown) + { + // Pop-up menu? + if (ev->data1 == KEY_ESCAPE) // Should we let the games handle Escape for special actions, like backing out of cameras? + { + M_StartControlPanel(true); + M_SetMenu(NAME_IngameMenu, -1); + return true; + } + return false; + } + else if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_LButtonDown && + ConsoleState != c_down && m_use_mouse) + { + M_StartControlPanel(true); + M_SetMenu(NAME_MainMenu, -1); + return true; + } + } + return false; +} + +bool M_Responder(event_t* ev) +{ + // delayed deletion, so that self-deleting menus don't crash if they are getting accessed after being closed. + auto res = M_DoResponder(ev); + for (auto p : toDelete) delete p; + toDelete.Clear(); + return res; +} + +//============================================================================= +// +// +// +//============================================================================= + +void M_Ticker (void) +{ + DMenu::MenuTime++; + if (DMenu::MenuTime & 3) return; + if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off) + { + D_ProcessEvents(); // The main loop is blocked when the menu is open and cannot dispatch the events. + if (transition.previous) transition.previous->Ticker(); + if (DMenu::CurrentMenu == nullptr) return; // In case one of the sub-screens has closed the menu. + DMenu::CurrentMenu->Ticker(); + + for (int i = 0; i < NUM_MKEYS; ++i) + { + if (MenuButtons[i].bDown) + { + if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0) + { + MenuButtonTickers[i] = KEY_REPEAT_RATE; + DMenu::CurrentMenu->MenuEvent(i, MenuButtonOrigin[i]); + } + } + } + if (BackbuttonTime > 0) + { + if (BackbuttonAlpha < 1.0f) BackbuttonAlpha += 0.1f; + BackbuttonTime--; + } + else + { + if (BackbuttonAlpha > 0) BackbuttonAlpha -= 0.1f; + if (BackbuttonAlpha < 0) BackbuttonAlpha = 0; + } + } +} + +//============================================================================= +// +// +// +//============================================================================= + +void M_Drawer (void) +{ + rotatesprite_2doverride = true; + PalEntry fade = 0x70000000; + + if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off) + { + if (DMenu::CurrentMenu->DimAllowed() && fade && !DrawBackground) twod.AddColorOnlyQuad(0, 0, screen->GetWidth(), screen->GetHeight(), fade); + + bool going = false; + if (transition.previous) + { + going = transition.Draw(); + if (!going) + { + if (transition.dir == -1) delete transition.previous; + transition.previous = nullptr; + transition.current = nullptr; + } + } + if (!going) + { + DMenu::CurrentMenu->origin = { 0,0 }; + // else if (DrawBackground) Menu_DrawBackground(origin); + DMenu::CurrentMenu->Drawer(); + } + } + rotatesprite_2doverride = false; +} + +//============================================================================= +// +// +// +//============================================================================= + +void M_ClearMenus () +{ + M_DemoNoPlay = false; + transition.previous = transition.current = nullptr; + transition.dir = 0; + auto menu = DMenu::CurrentMenu; + while (menu != nullptr) + { + auto nextm = menu->mParentMenu; + menu->Destroy(); + delete menu; + menu = nextm; + } + DMenu::CurrentMenu = nullptr; + menuactive = MENU_Off; + mouseGrabInput(true); + gi->MenuClosed(); +} + +void Menu_Close(int playerid) +{ + M_ClearMenus(); +} + +bool M_Active() +{ + return DMenu::CurrentMenu != nullptr || ConsoleState == c_down || ConsoleState == c_falling; +} + +//============================================================================= +// +// +// +//============================================================================= + +void M_MenuSound(EMenuSounds snd) +{ + if (menu_sounds) gi->MenuSound(snd); +} + +//============================================================================= +// +// +// +//============================================================================= + +void M_Init (void) +{ + RegisterDukeMenus(); + RegisterRedneckMenus(); + RegisterBloodMenus(); + RegisterSWMenus(); + RegisterLoadsaveMenus(); + RegisterOptionMenus(); + timerSetCallback(M_Ticker); + M_ParseMenuDefs(); +} + + +//============================================================================= +// +// +// +//============================================================================= + +void M_EnableMenu (bool on) +{ + MenuEnabled = on; +} + + +//============================================================================= +// +// [RH] Most menus can now be accessed directly +// through console commands. +// +//============================================================================= + + +CCMD (openmenu) +{ + if (argv.argc() < 2) + { + Printf("Usage: openmenu \"menu_name\""); + return; + } + M_StartControlPanel (true); + M_SetMenu(argv[1], -1); +} + +CCMD (closemenu) +{ + M_ClearMenus(); +} + +EXTERN_CVAR (Int, screenblocks) + +CCMD(menuconsole) +{ + M_ClearMenus(); + C_ToggleConsole(); +} + +CCMD(reset2defaults) +{ + C_SetDefaultBindings (); + C_SetCVarsToDefaults (); +} + +CCMD(reset2saved) +{ + GameConfig->DoGlobalSetup (); + GameConfig->DoGameSetup (currentGame); +} + +CCMD(openmainmenu) +{ + //gi->ClearSoundLocks(); + M_StartControlPanel(true); + M_SetMenu(NAME_IngameMenu); +} + +CCMD(openhelpmenu) +{ + if (!help_disabled) + { + M_StartControlPanel(true); + M_SetMenu(NAME_HelpMenu); + } +} + +CCMD(opensavemenu) +{ + if (gi->CanSave()) + { + M_StartControlPanel(true); + M_SetMenu(NAME_SaveGameMenu); + } +} + +CCMD(openloadmenu) +{ + M_StartControlPanel(true); + M_SetMenu(NAME_LoadGameMenu); +} diff --git a/source/common/menu/menu.h b/source/common/menu/menu.h new file mode 100644 index 000000000..79a809c24 --- /dev/null +++ b/source/common/menu/menu.h @@ -0,0 +1,862 @@ +#ifndef __M_MENU_MENU_H__ +#define __M_MENU_MENU_H__ + + + + +#include "c_cvars.h" +#include "v_font.h" +#include "version.h" +#include "textures.h" +#include "zstring.h" +#include "baselayer.h" + +EXTERN_CVAR(Float, snd_menuvolume) +EXTERN_CVAR(Int, m_use_mouse); + +enum EMax +{ + MAXSKILLS = 7, + MAXVOLUMES = 7, + MAXMENUGAMEPLAYENTRIES = 7, +}; + +// These get filled in by the map definition parsers of the front ends. +extern FString gSkillNames[MAXSKILLS]; +extern FString gVolumeNames[MAXVOLUMES]; +extern FString gVolumeSubtitles[MAXVOLUMES]; +extern int32_t gVolumeFlags[MAXVOLUMES]; +extern int gDefaultVolume, gDefaultSkill; + +const int MENU_TICRATE = 30; +extern bool help_disabled, credits_disabled; +extern int g_currentMenu; + +enum MenuTransitionType +{ // Note: This enum is for logical categories, not visual types. + MA_None, + MA_Return, + MA_Advance, +}; + +class DMenu; + +struct MenuTransition +{ + DMenu* previous; + DMenu* current; + + int32_t start; + int32_t length; + int32_t dir; + + bool StartTransition(DMenu* from, DMenu* to, MenuTransitionType animtype); + bool Draw(); + +}; + +enum +{ + EF_HIDEFROMSP = 1 << 0, +}; + +enum MenuGameplayEntryFlags +{ + MGE_Locked = 1u << 0u, + MGE_Hidden = 1u << 1u, + MGE_UserContent = 1u << 2u, +}; + +typedef struct MenuGameplayEntry +{ + char name[64]; + uint8_t flags; + + bool isValid() const { return name[0] != '\0'; } +} MenuGameplayEntry; + +typedef struct MenuGameplayStemEntry +{ + MenuGameplayEntry entry; + MenuGameplayEntry subentries[MAXMENUGAMEPLAYENTRIES]; +} MenuGameplayStemEntry; + +extern MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES]; + + +enum EMenuState : int +{ + MENU_Off, // Menu is closed + MENU_On, // Menu is opened + MENU_WaitKey, // Menu is opened and waiting for a key in the controls menu + MENU_OnNoPause, // Menu is opened but does not pause the game +}; + +enum EMenuSounds : int +{ + ActivateSound, + CursorSound, + AdvanceSound, + BackSound, + CloseSound, + PageSound, + ChangeSound +}; + +EXTERN_CVAR(Bool, menu_sounds) + +struct event_t; +class FTexture; +class FFont; +enum EColorRange : int; +class FPlayerClass; +class FKeyBindings; + +enum EMenuKey +{ + MKEY_Up, + MKEY_Down, + MKEY_Left, + MKEY_Right, + MKEY_PageUp, + MKEY_PageDown, + //----------------- Keys past here do not repeat. + MKEY_Enter, + MKEY_Back, // Back to previous menu + MKEY_Clear, // Clear keybinding/flip player sprite preview + NUM_MKEYS, + + // These are not buttons but events sent from other menus + + MKEY_Input, // Sent when input is confirmed + MKEY_Abort, // Input aborted + MKEY_MBYes, + MKEY_MBNo, +}; + +enum ENativeFontValues +{ + NIT_BigFont, + NIT_SmallFont, + NIT_TinyFont, + + NIT_ActiveColor = -1, + NIT_InactiveColor = -2, + NIT_SelectedColor = -3, + + NIT_ActiveState = 1, + NIT_InactiveState = 2, + NIT_SelectedState = 3 + // positive values for color are direct palswap indices. +}; + +extern FGameStartup GameStartupInfo; +extern EMenuState menuactive; + + +//============================================================================= +// +// menu descriptor. This is created from the menu definition lump +// Items must be inserted in the order they are cycled through with the cursor +// +//============================================================================= + +enum EMenuDescriptorType +{ + MDESC_ListMenu, + MDESC_OptionsMenu, + MDESC_ImageScroller, +}; + +struct FMenuDescriptor +{ + FName mMenuName; + FString mNetgameMessage; + int mType; + FName mClass; + + virtual ~FMenuDescriptor() {} +}; + +class FListMenuItem; +class FOptionMenuItem; + +enum ListMenuFlags +{ + LMF_Centered = 1, + LMF_DontSpace = 2, + LMF_Animate = 4, +}; + +struct FListMenuDescriptor : public FMenuDescriptor +{ + TDeletingArray mItems; + FString mCaption; + int mSelectedItem; + int mSelectOfsX; + int mSelectOfsY; + FTexture *mSelector; + int mDisplayTop; + int mXpos, mYpos, mYbotton; + int mWLeft, mWRight; + int mLinespacing; // needs to be stored for dynamically created menus + int mAutoselect; // this can only be set by internal menu creation functions + int mScriptId; + int mSecondaryId; + int mNativeFontNum, mNativePalNum; + float mNativeFontScale; + FFont *mFont; + EColorRange mFontColor; + EColorRange mFontColor2; + FMenuDescriptor *mRedirect; // used to redirect overlong skill and episode menus to option menu based alternatives + int mFlags; + int mSpacing; + + FListMenuDescriptor() + { + Reset(); + } + + void Reset() + { + // Reset the default settings (ignore all other values in the struct) + mSelectOfsX = 0; + mSelectOfsY = 0; + mSelector = nullptr; + mDisplayTop = 0; + mXpos = 0; + mYpos = 0; + mLinespacing = 0; + mNetgameMessage = ""; + mFont = NULL; + mFontColor = CR_UNTRANSLATED; + mFontColor2 = CR_UNTRANSLATED; + mScriptId = -1; + mSecondaryId = 0; + mNativeFontNum = NIT_BigFont; + mNativePalNum = NIT_ActiveColor; + mNativeFontScale = 1.f; + mFlags = 0; + mSpacing = 0; + } +}; + +struct FOptionMenuSettings +{ + EColorRange mTitleColor; + EColorRange mFontColor; + EColorRange mFontColorValue; + EColorRange mFontColorMore; + EColorRange mFontColorHeader; + EColorRange mFontColorHighlight; + EColorRange mFontColorSelection; + int mLinespacing; +}; + +struct FOptionMenuDescriptor : public FMenuDescriptor +{ + TDeletingArray mItems; + FString mTitle; + int mSelectedItem; + int mDrawTop; + int mScrollTop; + int mScrollPos; + int mIndent; + int mPosition; + bool mDontDim; + + void CalcIndent(); + FOptionMenuItem *GetItem(FName name); + void Reset() + { + // Reset the default settings (ignore all other values in the struct) + mPosition = 0; + mScrollTop = 0; + mIndent = 0; + mDontDim = 0; + } + +}; + +struct FImageScrollerDescriptor : public FMenuDescriptor +{ + struct ScrollerItem + { + int type; // 0: fullscreen image; 1: centered text + int scriptID; + FString text; + }; + int mFlags = 0; + + TArray mItems; +}; + + + +typedef TMap MenuDescriptorList; + +extern FOptionMenuSettings OptionSettings; +extern MenuDescriptorList MenuDescriptors; + +#define CURSORSPACE (14 * CleanXfac_1) + +//============================================================================= +// +// +// +//============================================================================= + +struct FMenuRect +{ + int x, y; + int width, height; + + void set(int _x, int _y, int _w, int _h) + { + x = _x; + y = _y; + width = _w; + height = _h; + } + + bool inside(int _x, int _y) + { + return _x >= x && _x < x+width && _y >= y && _y < y+height; + } + +}; + + +class DMenu +{ +protected: + bool mMouseCapture; + bool mBackbuttonSelected; + +public: + enum + { + MOUSE_Click, + MOUSE_Move, + MOUSE_Release + }; + + enum + { + BACKBUTTON_TIME = 4*MENU_TICRATE + }; + + static DMenu *CurrentMenu; + static int MenuTime; + + DMenu *mParentMenu; + DVector2 origin = { 0,0 }; + int scriptID = INT_MAX; + bool canAnimate = false; + + DMenu(DMenu *parent = NULL); + virtual ~DMenu() = default; + virtual bool Responder (event_t *ev); + virtual bool MenuEvent (int mkey, bool fromcontroller); + virtual void Ticker (); + virtual void PreDraw() {} + virtual void PostDraw() {} + virtual void Drawer (); + virtual bool DimAllowed (); + virtual bool TranslateKeyboardEvents(); + virtual void Close(); + virtual bool MouseEvent(int type, int x, int y); + virtual void Destroy() {} + bool MouseEventBack(int type, int x, int y); + void SetCapture(); + void ReleaseCapture(); + void SetOrigin(); + bool HasCapture() + { + return mMouseCapture; + } +}; + +//============================================================================= +// +// base class for menu items +// +//============================================================================= + +class DListMenu; + +class FListMenuItem +{ +protected: + int mXpos, mYpos; + int mHeight; + FName mAction; + +public: + bool mEnabled, mHidden; + + FListMenuItem(int xpos = 0, int ypos = 0, FName action = NAME_None) + { + mXpos = xpos; + mYpos = ypos; + mAction = action; + mEnabled = true; + mHidden = false; + } + + virtual ~FListMenuItem(); + + virtual bool CheckCoordinate(int x, int y); + virtual void Ticker(); + virtual void Drawer(DListMenu *menu, const DVector2& origin, bool selected); + virtual bool Selectable(); + virtual bool Activate(FName caller); + virtual FName GetAction(int *pparam); + virtual bool SetString(int i, const char *s); + virtual bool GetString(int i, char *s, int len); + virtual bool SetValue(int i, int value); + virtual bool GetValue(int i, int *pvalue); + virtual void Enable(bool on); + virtual bool MenuEvent (int mkey, bool fromcontroller); + virtual bool MouseEvent(int type, int x, int y); + virtual bool CheckHotkey(int c); + virtual int GetWidth(); + virtual void DrawSelector(int xofs, int yofs, FTexture *tex); + void OffsetPositionY(int ydelta) { mYpos += ydelta; } + int GetY() { return mYpos; } + int GetX() { return mXpos; } + void SetX(int x) { mXpos = x; } + void SetY(int x) { mYpos = x; } + void SetHeight(int x) { mHeight = x; } + void SetAction(FName action) { mAction = action; } +}; + +class FListMenuItemStaticPatch : public FListMenuItem +{ +protected: + FTexture *mTexture; + bool mCentered; + +public: + FListMenuItemStaticPatch(int x, int y, FTexture *patch, bool centered); + void Drawer(DListMenu* menu, const DVector2& origin, bool selected); +}; + +class FListMenuItemStaticText : public FListMenuItem +{ +protected: + const char *mText; + FFont *mFont; + EColorRange mColor; + bool mCentered; + +public: + FListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered); + ~FListMenuItemStaticText(); + void Drawer(DListMenu* menu, const DVector2& origin, bool selected) override; +}; + +class FListMenuItemNativeStaticText : public FListMenuItem +{ +protected: + FString mText; + int mFontnum; + int mPalnum; + bool mCentered; + +public: + FListMenuItemNativeStaticText(int x, int y, const FString & text, int fontnum, int palnum, bool centered); + void Drawer(DListMenu* menu, const DVector2& origin, bool selected) override; +}; + +//============================================================================= +// +// selectable items +// +//============================================================================= + +class FListMenuItemSelectable : public FListMenuItem +{ +protected: + int mHotkey; + int mParam; + +public: + FListMenuItemSelectable(int x, int y, int height, FName childmenu, int mParam = -1); + bool CheckCoordinate(int x, int y) override; + bool Selectable() override; + bool CheckHotkey(int c) override; + bool Activate(FName caller) override; + bool MouseEvent(int type, int x, int y) override; + FName GetAction(int *pparam) override; +}; + +class FListMenuItemText : public FListMenuItemSelectable +{ + FString mText; + FFont *mFont; + EColorRange mColor; + EColorRange mColorSelected; +public: + FListMenuItemText(int x, int y, int height, int hotkey, const FString &text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0); + ~FListMenuItemText(); + void Drawer(DListMenu* menu, const DVector2& origin, bool selected) override; + int GetWidth() override; +}; + +class FListMenuItemNativeText : public FListMenuItemSelectable +{ + // This draws the item with the game frontend's native text drawer and uses a front end defined font, it takes only symbolic constants as parameters. + FString mText; + int mFontnum; + int mPalnum; + float mFontscale; +public: + FListMenuItemNativeText(int x, int y, int height, int hotkey, const FString& text, int fontnum, int palnum, float fontscale, FName child, int param = 0); + ~FListMenuItemNativeText(); + void Drawer(DListMenu* menu, const DVector2& origin, bool selected) override; + int GetWidth() override; + void DrawSelector(int xofs, int yofs, FTexture* tex) override { } // The text drawer handles this itself. +}; + + +class FListMenuItemPatch : public FListMenuItemSelectable +{ + FTexture* mTexture; +public: + FListMenuItemPatch(int x, int y, int height, int hotkey, FTexture* patch, FName child, int param = 0); + void Drawer(DListMenu* menu, const DVector2& origin, bool selected) override; + int GetWidth() override; +}; + +//============================================================================= +// +// list menu class runs a menu described by a FListMenuDescriptor +// +//============================================================================= + +class DListMenu : public DMenu +{ + typedef DMenu Super; +protected: + FListMenuDescriptor *mDesc = nullptr; + FListMenuItem *mFocusControl = nullptr; + +public: + DListMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL); + virtual void Init(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL); + FListMenuItem *GetItem(FName name); + bool Responder (event_t *ev) override; + bool MenuEvent (int mkey, bool fromcontroller) override; + bool MouseEvent(int type, int x, int y) override; + void Ticker () override; + void Drawer () override; + void PreDraw() override; + virtual void SelectionChanged() {} + void SetFocus(FListMenuItem *fc) + { + mFocusControl = fc; + } + bool CheckFocus(FListMenuItem *fc) + { + return mFocusControl == fc; + } + void ReleaseFocus() + { + mFocusControl = NULL; + } + const FListMenuDescriptor* Descriptor() const + { + return mDesc; + } +}; + + +//============================================================================= +// +// base class for menu items +// +//============================================================================= + +class FOptionMenuItem : public FListMenuItem +{ +protected: + FString mLabel; + bool mCentered = false; + + void drawText(int x, int y, int color, const char * text, bool grayed = false); + + int drawLabel(int indent, int y, EColorRange color, bool grayed = false); + void drawValue(int indent, int y, int color, const char *text, bool grayed = false); + + int CursorSpace(); + + +public: + + FOptionMenuItem(const char *text, FName action = NAME_None, bool center = false) + : FListMenuItem(0, 0, action) + { + mLabel = text; + mCentered = center; + } + + ~FOptionMenuItem(); + virtual int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected); + virtual bool Selectable(); + virtual int GetIndent(); + virtual bool MouseEvent(int type, int x, int y); +}; + +//============================================================================= +// +// +// +//============================================================================= +struct FOptionValues +{ + struct Pair + { + double Value; + FString TextValue; + FString Text; + }; + + TArray mValues; +}; + +typedef TMap< FName, FOptionValues* > FOptionMap; + +extern FOptionMap OptionValues; + + +//============================================================================= +// +// Option menu class runs a menu described by a FOptionMenuDescriptor +// +//============================================================================= + +class DOptionMenu : public DMenu +{ + using Super = DMenu; + bool CanScrollUp; + bool CanScrollDown; + int VisBottom; + FOptionMenuItem *mFocusControl; + +protected: + FOptionMenuDescriptor *mDesc; + +public: + FOptionMenuItem *GetItem(FName name); + DOptionMenu(DMenu *parent = NULL, FOptionMenuDescriptor *desc = NULL); + virtual void Init(DMenu *parent = NULL, FOptionMenuDescriptor *desc = NULL); + int FirstSelectable(); + bool Responder (event_t *ev); + bool MenuEvent (int mkey, bool fromcontroller); + bool MouseEvent(int type, int x, int y); + void Ticker (); + void Drawer (); + virtual int GetIndent(); + const FOptionMenuDescriptor *GetDescriptor() const { return mDesc; } + void SetFocus(FOptionMenuItem *fc) + { + mFocusControl = fc; + } + bool CheckFocus(FOptionMenuItem *fc) + { + return mFocusControl == fc; + } + void ReleaseFocus() + { + mFocusControl = NULL; + } +}; + +FFont *OptionFont(); +int OptionHeight(); +int OptionWidth(const char * s); +void DrawOptionText(int x, int y, int color, const char *text, bool grayed = false); + +//============================================================================= +// +// ImageScroller +// +//============================================================================= +class ImageScreen; + +class DImageScrollerMenu : public DMenu +{ + DMenu* mCurrent = nullptr; + FImageScrollerDescriptor* mDesc = nullptr; + int index = 0; + MenuTransition pageTransition = {}; + +protected: + virtual ImageScreen* newImageScreen(FImageScrollerDescriptor::ScrollerItem* desc); + +public: + void Init(DMenu* parent = nullptr, FImageScrollerDescriptor* desc = nullptr); + bool MenuEvent(int mkey, bool fromcontroller); + bool MouseEvent(int type, int x, int y); + void Ticker(); + void Drawer(); +}; + +//============================================================================= +// +// Input some text +// +//============================================================================= + +class DTextEnterMenu : public DMenu +{ + using Super = DMenu; + + FString mEnterString; + int mEnterSize; + int mEnterPos; + bool mInputGridOkay; + int InputGridX; + int InputGridY; + int CursorSize; + bool AllowColors; + FFont *displayFont; + + + void AppendChar(int ch); + +public: + + // [TP] Added allowcolors + DTextEnterMenu(DMenu *parent, FFont *dpf, FString textbuffer, int maxlen, bool showgrid, bool allowcolors = false); + + void Drawer (); + bool MenuEvent (int mkey, bool fromcontroller); + bool Responder(event_t *ev); + bool TranslateKeyboardEvents(); + bool MouseEvent(int type, int x, int y); + const char* GetText() { return mEnterString.GetChars(); } + +}; + +//============================================================================= +// +// Show a fullscreen image / centered text screen for an image scroller +// +//============================================================================= + +class ImageScreen : public DMenu +{ +protected: + const FImageScrollerDescriptor::ScrollerItem* mDesc; +public: + ImageScreen(const FImageScrollerDescriptor::ScrollerItem* it) + { + mDesc = it; + } + void Drawer() override; +}; + + + +struct event_t; +void M_EnableMenu (bool on) ; +bool M_Responder (event_t *ev); +void M_Ticker (void); +void M_Drawer (void); +void M_Init (void); +void M_CreateMenus(); +void M_ActivateMenu(DMenu *menu); +void M_ClearMenus (); +void M_ParseMenuDefs(); +void M_StartupSkillMenu(FGameStartup *gs); +int M_GetDefaultSkill(); +void M_StartControlPanel (bool makeSound); +bool M_SetMenu(FName menu, int param = -1, FName callingMenu = NAME_None); +void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave); +void M_StartMessage(const char *message, int messagemode, int scriptId, FName action = NAME_None); +void M_UnhideCustomMenu(int menu, int itemmask); +void M_MenuSound(EMenuSounds snd); +void M_Autosave(); +bool M_Active(); + + +void I_SetMouseCapture(); +void I_ReleaseMouseCapture(); + +struct MenuClassDescriptor; +extern TArray menuClasses; + +using hFunc = std::function; +DMenu* CreateMessageBoxMenu(DMenu* parent, const char* message, int messagemode, int scriptID, bool playsound, FName action = NAME_None, hFunc handler = nullptr); + + +struct MenuClassDescriptor +{ + FName mName; + MenuClassDescriptor(const char* name) : mName(name) + { + //menuClasses.Push(this); + } + + virtual DMenu* CreateNew() = 0; +}; + +template struct TMenuClassDescriptor : public MenuClassDescriptor +{ + TMenuClassDescriptor(const char* name) : MenuClassDescriptor(name) + {} + DMenu* CreateNew() + { + return new Menu; + } +}; + + +struct FSavegameManager +{ +private: + TArray SaveGames; + FSaveGameNode NewSaveNode; + int LastSaved = -1; + int LastAccessed = -1; + TArray SavePicData; + FTexture *SavePic = nullptr; + +public: + int WindowSize = 0; + FString SaveCommentString; + FSaveGameNode *quickSaveSlot = nullptr; + ~FSavegameManager(); + +private: + int InsertSaveNode(FSaveGameNode *node); +public: + void NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave); + void ClearSaveGames(); + + void ReadSaveStrings(); + void UnloadSaveData(); + + int RemoveSaveSlot(int index); + void LoadSavegame(int Selected); + void DoSave(int Selected, const char *savegamestring); + unsigned ExtractSaveData(int index); + void ClearSaveStuff(); + bool DrawSavePic(int x, int y, int w, int h); + void DrawSaveComment(FFont *font, int cr, int x, int y, int scalefactor); + void SetFileInfo(int Selected); + unsigned SavegameCount(); + FSaveGameNode *GetSavegame(int i); + void InsertNewSaveNode(); + bool RemoveNewSaveNode(); + + void LoadGame(FSaveGameNode* node); + void SaveGame(FSaveGameNode* node, bool ok4q, bool forceq); + +}; + +extern FSavegameManager savegameManager; + +#endif diff --git a/source/common/menu/menudef.cpp b/source/common/menu/menudef.cpp new file mode 100644 index 000000000..94bedc889 --- /dev/null +++ b/source/common/menu/menudef.cpp @@ -0,0 +1,1517 @@ +/* +** menudef.cpp +** MENUDEF parser amd menu generation code +** +**--------------------------------------------------------------------------- +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ +#include + +#include "menu.h" +#include "c_dispatch.h" +#include "filesystem.h" +#include "sc_man.h" +#include "v_font.h" +#include "c_bind.h" +#include "d_event.h" +#include "d_gui.h" +#include "printf.h" +#include "gamecontrol.h" +#include "cmdlib.h" +#include "c_cvars.h" +#include "optionmenuitems.h" +#include "i_soundfont.h" +#include "zmusic/zmusic.h" + +// Menu-relevant content that gets filled in by scripts. This will get processed after the game has loaded. +FString gSkillNames[MAXSKILLS]; +FString gVolumeNames[MAXVOLUMES]; +FString gVolumeSubtitles[MAXVOLUMES]; +int32_t gVolumeFlags[MAXVOLUMES]; +int gDefaultVolume = 0, gDefaultSkill = 1; +MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES]; + +MenuDescriptorList MenuDescriptors; +static FListMenuDescriptor DefaultListMenuSettings; // contains common settings for all list menus +static FOptionMenuDescriptor DefaultOptionMenuSettings; // contains common settings for all Option menus +FOptionMenuSettings OptionSettings; +FOptionMap OptionValues; + +void I_BuildMIDIMenuList(FOptionValues* opt); +void I_BuildALDeviceList(FOptionValues *opt); +void I_BuildALResamplersList(FOptionValues* opt); + +static void DeinitMenus() +{ + { + MenuDescriptorList::Iterator it(MenuDescriptors); + + MenuDescriptorList::Pair *pair; + + while (it.NextPair(pair)) + { + delete pair->Value; + pair->Value = NULL; + } + } + + { + FOptionMap::Iterator it(OptionValues); + + FOptionMap::Pair *pair; + + while (it.NextPair(pair)) + { + delete pair->Value; + pair->Value = NULL; + } + } + MenuDescriptors.Clear(); + OptionValues.Clear(); + DMenu::CurrentMenu = NULL; + DefaultListMenuSettings.mItems.Clear(); +} + +static FTexture* GetMenuTexture(const char* const name) +{ + auto tex = TileFiles.GetTexture(name); + + if (!tex) + { + Printf("Missing menu texture: \"%s\"\n", name); + } + + return tex; +} + +//============================================================================= +// +// +// +//============================================================================= + +static void SkipSubBlock(FScanner &sc) +{ + sc.MustGetStringName("{"); + int depth = 1; + while (depth > 0) + { + sc.MustGetString(); + if (sc.Compare("{")) depth++; + if (sc.Compare("}")) depth--; + } +} + +//============================================================================= +// +// +// +//============================================================================= + +struct gamefilter +{ + const char* gamename; + int gameflag; +}; + +static const gamefilter games[] = { + { "Duke", GAMEFLAG_DUKE}, + { "Nam", GAMEFLAG_NAM|GAMEFLAG_NAPALM}, + { "NamOnly", GAMEFLAG_NAM}, // for cases where the difference matters. + { "Napalm", GAMEFLAG_NAPALM}, + { "WW2GI", GAMEFLAG_WW2GI}, + { "Fury", GAMEFLAG_FURY}, + { "Redneck", GAMEFLAG_RR}, + { "RedneckRides", GAMEFLAG_RRRA}, + { "Blood", GAMEFLAG_BLOOD}, + { "ShadowWarrior", GAMEFLAG_SW}, +}; + +// for other parts that need to filter by game name. +bool validFilter(const char *str) +{ + for (auto &gf : games) + { + if (g_gameType & gf.gameflag) + { + if (!stricmp(str, gf.gamename)) return true; + } + } + return false; +} + + +static bool CheckSkipGameBlock(FScanner &sc) +{ + int filter = 0; + sc.MustGetStringName("("); + do + { + sc.MustGetString(); + int gi = sc.MustMatchString(&games[0].gamename, sizeof(games[0])); + + filter |= games[gi].gameflag; + } + while (sc.CheckString(",")); + sc.MustGetStringName(")"); + if (!(filter & g_gameType)) + { + SkipSubBlock(sc); + return !sc.CheckString("else"); + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +static bool CheckSkipOptionBlock(FScanner &sc) +{ + bool filter = false; + sc.MustGetStringName("("); + do + { + sc.MustGetString(); + if (sc.Compare("Windows")) + { + #ifdef _WIN32 + filter = true; + #endif + } + else if (sc.Compare("unix")) + { + #ifdef __unix__ + filter = true; + #endif + } + else if (sc.Compare("Mac")) + { + #ifdef __APPLE__ + filter = true; + #endif + } + } + while (sc.CheckString(",")); + sc.MustGetStringName(")"); + if (!filter) + { + SkipSubBlock(sc); + return !sc.CheckString("else"); + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +static bool CheckSkipNoSwBlock(FScanner& sc) +{ + sc.MustGetStringName("("); + sc.MustGetString(); + bool res = sc.Compare("true"); + sc.MustGetStringName(")"); + if ((!(g_gameType & GAMEFLAG_SHAREWARE)) == res) + { + SkipSubBlock(sc); + return !sc.CheckString("else"); + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) +{ + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("else")) + { + SkipSubBlock(sc); + } + else if (sc.Compare("ifgame")) + { + if (!CheckSkipGameBlock(sc)) + { + // recursively parse sub-block + ParseListMenuBody(sc, desc); + } + } + else if (sc.Compare("ifoption")) + { + if (!CheckSkipOptionBlock(sc)) + { + // recursively parse sub-block + ParseListMenuBody(sc, desc); + } + } + else if (sc.Compare("ifshareware")) + { + if (!CheckSkipNoSwBlock(sc)) + { + // recursively parse sub-block + ParseListMenuBody(sc, desc); + } + } + else if (sc.Compare("Class")) + { + sc.MustGetString(); + desc->mClass = sc.String; + } + else if (sc.Compare("Selector")) + { + sc.MustGetString(); + desc->mSelector = GetMenuTexture(sc.String); + sc.MustGetStringName(","); + sc.MustGetNumber(); + desc->mSelectOfsX = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + desc->mSelectOfsY = sc.Number; + } + else if (sc.Compare("Linespacing")) + { + sc.MustGetNumber(); + desc->mLinespacing = sc.Number; + } + else if (sc.Compare("Position")) + { + sc.MustGetNumber(); + desc->mXpos = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + desc->mYpos = sc.Number; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + desc->mYbotton = sc.Number; + } + } + else if (sc.Compare("Centermenu")) + { + desc->mFlags |= LMF_Centered; + } + else if (sc.Compare("animatedtransition")) + { + desc->mFlags |= LMF_Animate; + } + else if (sc.Compare("Fixedspacing")) + { + sc.MustGetNumber(); + desc->mSpacing = sc.Number; + } + else if (sc.Compare("MouseWindow")) + { + sc.MustGetNumber(); + desc->mWLeft = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + desc->mWRight = sc.Number; + } + else if (sc.Compare("StaticPatch") || sc.Compare("StaticPatchCentered")) + { + bool centered = sc.Compare("StaticPatchCentered"); + sc.MustGetNumber(); + int x = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + int y = sc.Number; + sc.MustGetStringName(","); + sc.MustGetString(); + FTexture* tex = GetMenuTexture(sc.String); + + FListMenuItem *it = new FListMenuItemStaticPatch(x, y, tex, centered); + desc->mItems.Push(it); + } + else if (sc.Compare("ScriptId")) + { + sc.MustGetNumber(); + desc->mScriptId = sc.Number; + } + else if (sc.Compare("Caption")) + { + sc.MustGetString(); + desc->mCaption = sc.String; + } + else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered")) + { + bool centered = sc.Compare("StaticTextCentered"); + sc.MustGetNumber(); + int x = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + int y = sc.Number; + sc.MustGetStringName(","); + sc.MustGetString(); + FListMenuItem *it = new FListMenuItemStaticText(x, y, sc.String, desc->mFont, desc->mFontColor, centered); + desc->mItems.Push(it); + } + else if (sc.Compare("PatchItem")) + { + sc.MustGetString(); + FTexture* tex = GetMenuTexture(sc.String); + sc.MustGetStringName(","); + sc.MustGetString(); + int hotkey = sc.String[0]; + sc.MustGetStringName(","); + sc.MustGetString(); + FName action = sc.String; + int param = 0; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + param = sc.Number; + } + + FListMenuItem *it = new FListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); + desc->mItems.Push(it); + desc->mYpos += desc->mLinespacing; + if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; + } + else if (sc.Compare("TextItem")) + { + sc.MustGetString(); + FString text = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + int hotkey = sc.String[0]; + sc.MustGetStringName(","); + sc.MustGetString(); + FName action = sc.String; + int param = 0; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + param = sc.Number; + } + + FListMenuItem *it = new FListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); + desc->mItems.Push(it); + desc->mYpos += desc->mLinespacing; + if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; + + } + else if (sc.Compare("NativeTextItem")) + { + sc.MustGetString(); + FString text = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + int hotkey = sc.String[0]; + sc.MustGetStringName(","); + sc.MustGetString(); + FName action = sc.String; + int param = 0; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + param = sc.Number; + } + + auto it = new FListMenuItemNativeText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mNativeFontNum, desc->mNativePalNum, desc->mNativeFontScale, action, param); + desc->mItems.Push(it); + desc->mYpos += desc->mLinespacing; + if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size() - 1; + + } + else if (sc.Compare("NativeFont")) + { + desc->mNativePalNum = NIT_ActiveColor; + desc->mNativeFontScale = 1.f; + sc.MustGetString(); + if (sc.Compare("Big")) desc->mNativeFontNum = NIT_BigFont; + else if (sc.Compare("Small")) desc->mNativeFontNum = NIT_SmallFont; + else if (sc.Compare("Tiny")) desc->mNativeFontNum = NIT_TinyFont; + else sc.ScriptError("Unknown native font type"); + if (sc.CheckString(",")) + { + sc.MustGetString(); + if (sc.Compare("Active")) desc->mNativePalNum = NIT_ActiveColor; + else if (sc.Compare("Inactive")) desc->mNativePalNum = NIT_InactiveColor; + else if (sc.Compare("Selected")) desc->mNativePalNum = NIT_SelectedColor; + else + { + char* ep; + int v = (int)strtoll(sc.String, &ep, 0); + if (*ep != 0) sc.ScriptError("Unknown native palette"); + desc->mNativePalNum = v; + } + if (sc.CheckString(",")) + { + sc.MustGetFloat(); + desc->mNativeFontScale = sc.Float; + } + } + } + else if (sc.Compare("Font")) + { + sc.MustGetString(); + FFont* newfont = V_GetFont(sc.String); + if (newfont != NULL) desc->mFont = newfont; + if (sc.CheckString(",")) + { + sc.MustGetString(); + desc->mFontColor2 = desc->mFontColor = V_FindFontColor((FName)sc.String); + if (sc.CheckString(",")) + { + sc.MustGetString(); + desc->mFontColor2 = V_FindFontColor((FName)sc.String); + } + } + else + { + desc->mFontColor = OptionSettings.mFontColor; + desc->mFontColor2 = OptionSettings.mFontColorValue; + } + } + else if (sc.Compare("NetgameMessage")) + { + sc.MustGetString(); + desc->mNetgameMessage = sc.String; + } + else + { + sc.ScriptError("Unknown keyword '%s'", sc.String); + } + } +} + +//============================================================================= +// +// +// +//============================================================================= + +static bool CheckCompatible(FMenuDescriptor *newd, FMenuDescriptor *oldd) +{ + /*if (oldd->mClass == NULL)*/ return true; + //return oldd->mClass == newd->mClass; +} + +static bool ReplaceMenu(FScanner &sc, FMenuDescriptor *desc) +{ + FMenuDescriptor **pOld = MenuDescriptors.CheckKey(desc->mMenuName); + if (pOld != NULL && *pOld != NULL) + { + if (CheckCompatible(desc, *pOld)) + { + delete *pOld; + } + else + { + sc.ScriptMessage("Tried to replace menu '%s' with a menu of different type", desc->mMenuName.GetChars()); + return true; + } + } + MenuDescriptors[desc->mMenuName] = desc; + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseListMenu(FScanner &sc) +{ + sc.MustGetString(); + + FListMenuDescriptor *desc = new FListMenuDescriptor; + desc->mType = MDESC_ListMenu; + desc->mMenuName = sc.String; + desc->mSelectedItem = -1; + desc->mAutoselect = -1; + desc->mSelectOfsX = DefaultListMenuSettings.mSelectOfsX; + desc->mSelectOfsY = DefaultListMenuSettings.mSelectOfsY; + desc->mSelector = DefaultListMenuSettings.mSelector; + desc->mDisplayTop = DefaultListMenuSettings.mDisplayTop; + desc->mXpos = DefaultListMenuSettings.mXpos; + desc->mYpos = DefaultListMenuSettings.mYpos; + desc->mLinespacing = DefaultListMenuSettings.mLinespacing; + desc->mNetgameMessage = DefaultListMenuSettings.mNetgameMessage; + desc->mFont = DefaultListMenuSettings.mFont; + desc->mFontColor = DefaultListMenuSettings.mFontColor; + desc->mFontColor2 = DefaultListMenuSettings.mFontColor2; + desc->mClass = NULL; + desc->mRedirect = NULL; + desc->mWLeft = 0; + desc->mWRight = 0; + + ParseListMenuBody(sc, desc); + bool scratch = ReplaceMenu(sc, desc); + if (scratch) delete desc; +} + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseImageScrollerBody(FScanner &sc, FImageScrollerDescriptor *desc) +{ + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("else")) + { + SkipSubBlock(sc); + } + else if (sc.Compare("ifgame")) + { + if (!CheckSkipGameBlock(sc)) + { + // recursively parse sub-block + ParseImageScrollerBody(sc, desc); + } + } + else if (sc.Compare("ifshareware")) + { + if (!CheckSkipNoSwBlock(sc)) + { + // recursively parse sub-block + ParseImageScrollerBody(sc, desc); + } + } + else if (sc.Compare("ifoption")) + { + if (!CheckSkipOptionBlock(sc)) + { + // recursively parse sub-block + ParseImageScrollerBody(sc, desc); + } + } + else if (sc.Compare("Class")) + { + sc.MustGetString(); + desc->mClass = sc.String; + } + else if (sc.Compare("TextItem") || sc.Compare("ImageItem")) + { + FImageScrollerDescriptor::ScrollerItem item; + int type = sc.Compare("TextItem"); + sc.MustGetString(); + item.text = strbin1(sc.String); + if (type) + { + sc.MustGetStringName(","); + sc.MustGetNumber(); + item.type = sc.Number; // y-coordinate + } + else item.type = 0; + item.scriptID = INT_MAX; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + item.scriptID = sc.Number; + } + desc->mItems.Push(item); + } + else if (sc.Compare("qavanimationitem")) + { + if (!(g_gameType & GAMEFLAG_BLOOD)) + { + I_Error("QAV animations not available!"); // these (currently) only exist in Blood. + } + FImageScrollerDescriptor::ScrollerItem item; + sc.GetString(); + item.text = sc.String; + item.type = -1; + item.scriptID = INT_MAX; + desc->mItems.Push(item); + } + else if (sc.Compare("animatedtransition")) + { + desc->mFlags |= LMF_Animate; + } + else + { + sc.ScriptError("Unknown keyword '%s'", sc.String); + } + } +} + + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseImageScroller(FScanner &sc) +{ + sc.MustGetString(); + + FImageScrollerDescriptor *desc = new FImageScrollerDescriptor; + desc->mType = MDESC_ImageScroller; + desc->mMenuName = sc.String; + desc->mClass = NAME_None; + + ParseImageScrollerBody(sc, desc); + bool scratch = ReplaceMenu(sc, desc); + if (scratch) delete desc; +} + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseOptionValue(FScanner &sc) +{ + FName optname; + + FOptionValues *val = new FOptionValues; + sc.MustGetString(); + optname = sc.String; + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + FOptionValues::Pair &pair = val->mValues[val->mValues.Reserve(1)]; + sc.MustGetFloat(); + pair.Value = sc.Float; + sc.MustGetStringName(","); + sc.MustGetString(); + pair.Text = strbin1(sc.String); + } + FOptionValues **pOld = OptionValues.CheckKey(optname); + if (pOld != NULL && *pOld != NULL) + { + delete *pOld; + } + OptionValues[optname] = val; +} + + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseOptionString(FScanner &sc) +{ + FName optname; + + FOptionValues *val = new FOptionValues; + sc.MustGetString(); + optname = sc.String; + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + FOptionValues::Pair &pair = val->mValues[val->mValues.Reserve(1)]; + sc.MustGetString(); + pair.Value = DBL_MAX; + pair.TextValue = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + pair.Text = strbin1(sc.String); + } + FOptionValues **pOld = OptionValues.CheckKey(optname); + if (pOld != NULL && *pOld != NULL) + { + delete *pOld; + } + OptionValues[optname] = val; +} + + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseOptionSettings(FScanner &sc) +{ + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("else")) + { + SkipSubBlock(sc); + } + else if (sc.Compare("ifgame")) + { + if (!CheckSkipGameBlock(sc)) + { + // recursively parse sub-block + ParseOptionSettings(sc); + } + } + else if (sc.Compare("Linespacing")) + { + sc.MustGetNumber(); + OptionSettings.mLinespacing = sc.Number; + } + else if (sc.Compare("LabelOffset")) + { + sc.MustGetNumber(); + // ignored + } + else + { + sc.ScriptError("Unknown keyword '%s'", sc.String); + } + } +} + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc) +{ + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("else")) + { + SkipSubBlock(sc); + } + else if (sc.Compare("ifgame")) + { + if (!CheckSkipGameBlock(sc)) + { + // recursively parse sub-block + ParseOptionMenuBody(sc, desc); + } + } + else if (sc.Compare("ifshareware")) + { + if (!CheckSkipNoSwBlock(sc)) + { + // recursively parse sub-block + ParseOptionMenuBody(sc, desc); + } + } + else if (sc.Compare("ifoption")) + { + if (!CheckSkipOptionBlock(sc)) + { + // recursively parse sub-block + ParseOptionMenuBody(sc, desc); + } + } + else if (sc.Compare("Class")) + { + sc.MustGetString(); + desc->mClass = sc.String; + } + else if (sc.Compare("Title") || sc.Compare("Caption")) + { + sc.MustGetString(); + desc->mTitle = sc.String; + } + else if (sc.Compare("Position")) + { + sc.MustGetNumber(); + desc->mPosition = sc.Number; + } + else if (sc.Compare("DefaultSelection")) + { + sc.MustGetNumber(); + desc->mSelectedItem = sc.Number; + } + else if (sc.Compare("ScrollTop")) + { + sc.MustGetNumber(); + desc->mScrollTop = sc.Number; + } + else if (sc.Compare("Indent")) + { + sc.MustGetNumber(); + desc->mIndent = sc.Number; + } + else if (sc.Compare("Submenu")) + { + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FOptionMenuItem *it = new FOptionMenuItemSubmenu(label, sc.String); + desc->mItems.Push(it); + } + else if (sc.Compare("LabeledSubmenu")) + { + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + auto cvar = FindCVar(sc.String, nullptr); + sc.MustGetStringName(","); + sc.MustGetString(); + FOptionMenuItem* it = new FOptionMenuItemLabeledSubmenu(label, cvar, sc.String); + desc->mItems.Push(it); + } + else if (sc.Compare("Option")) + { + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FString cvar = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FString values = sc.String; + FString check; + int center = 0; + if (sc.CheckString(",")) + { + sc.MustGetString(); + if (*sc.String != 0) check = sc.String; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + center = sc.Number; + } + } + FOptionMenuItem *it = new FOptionMenuItemOption(label, cvar, values, check, center); + desc->mItems.Push(it); + } + else if (sc.Compare("Command")) + { + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FOptionMenuItem *it = new FOptionMenuItemCommand(label, sc.String); + desc->mItems.Push(it); + } + else if (sc.Compare("SafeCommand")) + { + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FOptionMenuItem *it = new FOptionMenuItemSafeCommand(label, sc.String); + desc->mItems.Push(it); + } + else if (sc.Compare("Control") || sc.Compare("MapControl")) + { + bool map = sc.Compare("MapControl"); + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FOptionMenuItem *it = new FOptionMenuItemControl(label, sc.String, map? &AutomapBindings : &Bindings); + desc->mItems.Push(it); + } + else if (sc.Compare("StaticText")) + { + sc.MustGetString(); + FString label = sc.String; + EColorRange cr = OptionSettings.mFontColorHeader; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + cr = sc.Number? OptionSettings.mFontColorHeader : OptionSettings.mFontColor; // fixme! + } + FOptionMenuItem *it = new FOptionMenuItemStaticText(label, cr); + desc->mItems.Push(it); + } + else if (sc.Compare("StaticTextSwitchable")) + { + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FString label2 = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FName action = sc.String; + EColorRange cr = OptionSettings.mFontColorHeader; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + cr = sc.Number ? OptionSettings.mFontColorHeader : OptionSettings.mFontColor; // fixme! + } + FOptionMenuItem *it = new FOptionMenuItemStaticTextSwitchable(label, label2, action, cr); + desc->mItems.Push(it); + } + else if (sc.Compare("Slider")) + { + sc.MustGetString(); + FString text = sc.String; + sc.MustGetStringName(","); + sc.MustGetString(); + FString action = sc.String; + sc.MustGetStringName(","); + sc.MustGetFloat(); + double min = sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + double max = sc.Float; + sc.MustGetStringName(","); + sc.MustGetFloat(); + double step = sc.Float; + int showvalue = 1; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + showvalue = sc.Number; + } + FOptionMenuItem *it = new FOptionMenuSliderCVar(text, action, min, max, step, showvalue); + desc->mItems.Push(it); + } + // [TP] -- Text input widget + else if ( sc.Compare( "TextField" )) + { + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName( "," ); + sc.MustGetString(); + FString cvar = sc.String; + FString check; + + if ( sc.CheckString( "," )) + { + sc.MustGetString(); + check = sc.String; + } + + FOptionMenuItem* it = new FOptionMenuTextField( label, cvar, check ); + desc->mItems.Push( it ); + } + // [TP] -- Number input widget + else if ( sc.Compare( "NumberField" )) + { + sc.MustGetString(); + FString label = sc.String; + sc.MustGetStringName( "," ); + sc.MustGetString(); + FString cvar = sc.String; + float minimum = 0.0f; + float maximum = 100.0f; + float step = 1.0f; + FString check; + + if ( sc.CheckString( "," )) + { + sc.MustGetFloat(); + minimum = (float) sc.Float; + sc.MustGetStringName( "," ); + sc.MustGetFloat(); + maximum = (float) sc.Float; + + if ( sc.CheckString( "," )) + { + sc.MustGetFloat(); + step = (float) sc.Float; + + if ( sc.CheckString( "," )) + { + sc.MustGetString(); + check = sc.String; + } + } + } + + FOptionMenuItem* it = new FOptionMenuNumberField( label, cvar, + minimum, maximum, step, check ); + desc->mItems.Push( it ); + } + else + { + sc.ScriptError("Unknown keyword '%s'", sc.String); + } + } +} + +//============================================================================= +// +// +// +//============================================================================= + +static void ParseOptionMenu(FScanner &sc) +{ + sc.MustGetString(); + + FOptionMenuDescriptor *desc = new FOptionMenuDescriptor; + desc->mType = MDESC_OptionsMenu; + desc->mMenuName = sc.String; + desc->mSelectedItem = -1; + desc->mScrollPos = 0; + desc->mClass = NULL; + desc->mPosition = DefaultOptionMenuSettings.mPosition; + desc->mScrollTop = DefaultOptionMenuSettings.mScrollTop; + desc->mIndent = DefaultOptionMenuSettings.mIndent; + desc->mDontDim = DefaultOptionMenuSettings.mDontDim; + + ParseOptionMenuBody(sc, desc); + bool scratch = ReplaceMenu(sc, desc); + if (scratch) delete desc; +} + + +//============================================================================= +// +// +// +//============================================================================= + +void M_ParseMenuDefs() +{ + int lump, lastlump = 0; + + //OptionSettings.mTitleColor = CR_RED;// V_FindFontColor(gameinfo.mTitleColor); + OptionSettings.mFontColor = CR_RED; + OptionSettings.mFontColorValue = CR_GRAY; + OptionSettings.mFontColorMore = CR_GRAY; + OptionSettings.mFontColorHeader = CR_GOLD; + OptionSettings.mFontColorHighlight = CR_YELLOW; + OptionSettings.mFontColorSelection = CR_BRICK; + + if (g_gameType & (GAMEFLAG_NAM | GAMEFLAG_NAPALM | GAMEFLAG_WW2GI)) + { + OptionSettings.mFontColor = CR_DARKGREEN; + OptionSettings.mFontColorHeader = CR_DARKGRAY; + OptionSettings.mFontColorHighlight = CR_WHITE; + OptionSettings.mFontColorSelection = CR_DARKGREEN; + } + else if (g_gameType & GAMEFLAG_BLOOD) + { + OptionSettings.mFontColorHeader = CR_DARKGRAY; + OptionSettings.mFontColorHighlight = CR_WHITE; + OptionSettings.mFontColorSelection = CR_DARKRED; + } + else if (g_gameType & GAMEFLAG_FURY) + { + OptionSettings.mFontColor = CR_TEAL; + OptionSettings.mFontColorHeader = CR_LIGHTBLUE; + OptionSettings.mFontColorHighlight = CR_ORANGE; + OptionSettings.mFontColorSelection = CR_GOLD; + } + else if (g_gameType & (GAMEFLAG_RR|GAMEFLAG_RRRA)) + { + OptionSettings.mFontColor = CR_BROWN; + OptionSettings.mFontColorHeader = CR_DARKBROWN; + OptionSettings.mFontColorHighlight = CR_ORANGE; + OptionSettings.mFontColorSelection = CR_TAN; + } + else if (g_gameType & GAMEFLAG_SW) + { + OptionSettings.mFontColorHeader = CR_DARKRED; + OptionSettings.mFontColorHighlight = CR_WHITE; + } + + DefaultListMenuSettings.Reset(); + DefaultOptionMenuSettings.Reset(); + + atexit(DeinitMenus); + DeinitMenus(); + while ((lump = fileSystem.Iterate("demolition/menudef.txt", &lastlump)) != -1) + { + FScanner sc(lump); + + sc.SetCMode(true); + while (sc.GetString()) + { + if (sc.Compare("LISTMENU")) + { + ParseListMenu(sc); + } + else if (sc.Compare("ImageScroller")) + { + ParseImageScroller(sc); + } + else if (sc.Compare("DEFAULTLISTMENU")) + { + ParseListMenuBody(sc, &DefaultListMenuSettings); + if (DefaultListMenuSettings.mItems.Size() > 0) + { + I_Error("You cannot add menu items to the menu default settings."); + } + } + else if (sc.Compare("OPTIONVALUE")) + { + ParseOptionValue(sc); + } + else if (sc.Compare("OPTIONSTRING")) + { + ParseOptionString(sc); + } + else if (sc.Compare("OPTIONMENUSETTINGS")) + { + ParseOptionSettings(sc); + } + else if (sc.Compare("OPTIONMENU")) + { + ParseOptionMenu(sc); + } + else if (sc.Compare("DEFAULTOPTIONMENU")) + { + ParseOptionMenuBody(sc, &DefaultOptionMenuSettings); + if (DefaultOptionMenuSettings.mItems.Size() > 0) + { + I_Error("You cannot add menu items to the menu default settings."); + } + } + else + { + sc.ScriptError("Unknown keyword '%s'", sc.String); + } + } + } +} + + +//============================================================================= +// +// Unlocks a custom menu from a script +// +//============================================================================= + +void M_UnhideCustomMenu(int menu, int iSet) +{ + FName menuname = FName(ENamedName(NAME_CustomSubMenu1 + menu)); + auto desc = MenuDescriptors.CheckKey(menuname); + if (desc != NULL && (*desc)->mType == MDESC_ListMenu) + { + FListMenuDescriptor* ld = static_cast(*desc); + for (unsigned int b = 0; b < MAXMENUGAMEPLAYENTRIES; ++b) + { + if (b >= ld->mItems.Size()) return; + if (iSet & (1u << b)) + { + ld->mItems[b]->mHidden = false; + ld->mItems[b]->mEnabled = true; + } + } + } +} + +//============================================================================= +// +// Creates the episode menu +// +//============================================================================= + +static void BuildEpisodeMenu() +{ + // Build episode menu + int addedVolumes = 0; + FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_EpisodeMenu); + if (desc != NULL && (*desc)->mType == MDESC_ListMenu) + { + FListMenuDescriptor *ld = static_cast(*desc); + ld->mSelectedItem = gDefaultVolume; + int y = ld->mYpos; + + for (int i = 0; i < MAXVOLUMES; i++) + { + if (gVolumeNames[i].IsNotEmpty() && !(gVolumeFlags[i] & EF_HIDEFROMSP)) + + { + auto it = new FListMenuItemNativeText(ld->mXpos, y, 0, gVolumeNames[i][0], gVolumeNames[i], NIT_BigFont, NIT_ActiveState, 1, NAME_SkillMenu, i); + y += ld->mLinespacing; + ld->mItems.Push(it); + addedVolumes++; + if (gVolumeSubtitles[i].IsNotEmpty()) + { + auto it = new FListMenuItemNativeStaticText(ld->mXpos, y, gVolumeSubtitles[i], NIT_SmallFont, NIT_ActiveState, false); + y += ld->mLinespacing * 6 / 10; + ld->mItems.Push(it); + } + } + } + if (!(g_gameType & GAMEFLAG_SHAREWARE)) + { + //auto it = new FListMenuItemNativeStaticText(ld->mXpos, "", NIT_SmallFont); // empty entry as spacer. + //ld->mItems.Push(it); + + y += ld->mLinespacing / 3; + auto it = new FListMenuItemNativeText(ld->mXpos, y, 0, 0, "$MNU_USERMAP", NIT_BigFont, NIT_ActiveState, 1, NAME_UsermapMenu); + ld->mItems.Push(it); + addedVolumes++; + } + if (addedVolumes == 1) + { + ld->mAutoselect = 0; + } + } + + // Build skill menu + int addedSkills = 0; + desc = MenuDescriptors.CheckKey(NAME_SkillMenu); + if (desc != NULL && (*desc)->mType == MDESC_ListMenu) + { + FListMenuDescriptor* ld = static_cast(*desc); + ld->mSelectedItem = gDefaultSkill; + int y = ld->mYpos; + + for (int i = 0; i < MAXSKILLS; i++) + { + if (gSkillNames[i].IsNotEmpty()) + { + auto it = new FListMenuItemNativeText(ld->mXpos, y, 0, gSkillNames[i][0], gSkillNames[i], NIT_BigFont, NIT_ActiveState, 1, NAME_StartGame, i); + y += ld->mLinespacing; + ld->mItems.Push(it); + addedSkills++; + } + } + if (addedSkills == 0) + { + // Need to add one item with the default skill so that the menu does not break. + auto it = new FListMenuItemNativeText(ld->mXpos, 0, 0, 0, "", NIT_BigFont, NIT_ActiveState, 1, NAME_StartGame, gDefaultSkill); + ld->mItems.Push(it); + } + if (addedSkills == 1) + { + ld->mAutoselect = 0; + } + } + + if (g_MenuGameplayEntries[0].entry.isValid()) + { + int e = 0; + FMenuDescriptor** desc = MenuDescriptors.CheckKey(NAME_CustomGameMenu); + if (desc != NULL && (*desc)->mType == MDESC_ListMenu) + { + FListMenuDescriptor* ldo = static_cast(*desc); + + for (MenuGameplayStemEntry const& stem : g_MenuGameplayEntries) + { + MenuGameplayEntry const& entry = stem.entry; + if (!entry.isValid()) + break; + + int s = 0; + FMenuDescriptor** sdesc = MenuDescriptors.CheckKey(FName(ENamedName(NAME_CustomSubMenu1 + e))); + if (sdesc != NULL && (*sdesc)->mType == MDESC_ListMenu) + { + FListMenuDescriptor* ld = static_cast(*sdesc); + ld->mCaption = entry.name; + + for (MenuGameplayEntry const& subentry : stem.subentries) + { + if (!subentry.isValid()) + break; + + auto li = new FListMenuItemNativeText(ld->mXpos, 0, 0, 0, subentry.name, NIT_BigFont, NIT_ActiveColor, 1.f, subentry.flags & MGE_UserContent ? NAME_UsermapMenu : NAME_SkillMenu); + + if (subentry.flags & MGE_Locked) li->mEnabled = false; + if (subentry.flags & MGE_Hidden) li->mHidden = true; + ld->mItems.Push(li); + ++s; + } + } + FName link = entry.flags & MGE_UserContent ? NAME_UsermapMenu : s == 0 ? NAME_SkillMenu : NAME_CustomSubMenu1; + + auto li = new FListMenuItemNativeText(ldo->mXpos, 0, 0, 0, entry.name, NIT_BigFont, NIT_ActiveColor, 1.f, link, e); + if (entry.flags & MGE_Locked) li->mEnabled = false; + if (entry.flags & MGE_Hidden) li->mHidden = true; + ldo->mItems.Push(li); + e++; + } + } + if (e > 0) + { + for (auto name : { NAME_MainMenu, NAME_IngameMenu }) + { + FMenuDescriptor** desc = MenuDescriptors.CheckKey(name); + if (desc != NULL && (*desc)->mType == MDESC_ListMenu) + { + FListMenuDescriptor* ld = static_cast(*desc); + auto li = ld->mItems[0]; + if (li->GetAction(nullptr) == NAME_EpisodeMenu) + { + li->SetAction(NAME_CustomGameMenu); + } + } + } + } + } +} + +//============================================================================= +// +// Reads any XHAIRS lumps for the names of crosshairs and +// adds them to the display options menu. +// +//============================================================================= + +static void InitCrosshairsList() +{ +#if 0 + int lastlump, lump; + + lastlump = 0; + + FOptionValues **opt = OptionValues.CheckKey(NAME_Crosshairs); + if (opt == NULL) + { + return; // no crosshair value list present. No need to go on. + } + + FOptionValues::Pair *pair = &(*opt)->mValues[(*opt)->mValues.Reserve(1)]; + pair->Value = 0; + pair->Text = "None"; + + while ((lump = Wads.FindLump("XHAIRS", &lastlump)) != -1) + { + FScanner sc(lump); + while (sc.GetNumber()) + { + FOptionValues::Pair value; + value.Value = sc.Number; + sc.MustGetString(); + value.Text = sc.String; + if (value.Value != 0) + { // Check if it already exists. If not, add it. + unsigned int i; + + for (i = 1; i < (*opt)->mValues.Size(); ++i) + { + if ((*opt)->mValues[i].Value == value.Value) + { + break; + } + } + if (i < (*opt)->mValues.Size()) + { + (*opt)->mValues[i].Text = value.Text; + } + else + { + (*opt)->mValues.Push(value); + } + } + } + } +#endif +} + +//============================================================================= +// +// Initialize the music configuration submenus +// +//============================================================================= +extern "C" +{ + extern int adl_getBanksCount(); + extern const char* const* adl_getBankNames(); +} + +static void InitMusicMenus() +{ + FMenuDescriptor** advmenu = MenuDescriptors.CheckKey(NAME_AdvSoundOptions); + auto soundfonts = sfmanager.GetList(); + std::tuple sfmenus[] = { + std::make_tuple("TimidityConfigMenu", SF_SF2 | SF_GUS, "timidity_config"), + std::make_tuple("FluidPatchsetMenu", SF_SF2, "fluid_patchset") }; + + for (auto& p : sfmenus) + { + FMenuDescriptor** menu = MenuDescriptors.CheckKey(std::get<0>(p)); + + if (menu != nullptr) + { + if (soundfonts.Size() > 0) + { + for (auto& entry : soundfonts) + { + if (entry.type & std::get<1>(p)) + { + FString display = entry.mName; + display.ReplaceChars("_", ' '); + auto it = new FOptionMenuItemCommand (display, FStringf("%s \"%s\"", std::get<2>(p), entry.mName.GetChars())/*, true*/); + static_cast(*menu)->mItems.Push(it); + } + } + } + else if (advmenu != nullptr) + { + // Remove the item for this submenu + auto d = static_cast(*advmenu); + auto it = d->GetItem(std::get<0>(p)); + if (it != nullptr) d->mItems.Delete(d->mItems.Find(it)); + } + } + } +} + +//============================================================================= +// +// Special menus will be created once all engine data is loaded +// +//============================================================================= + +void M_CreateMenus() +{ + BuildEpisodeMenu(); + InitCrosshairsList(); + InitMusicMenus(); + + FOptionValues** opt = OptionValues.CheckKey(NAME_Mididevices); + if (opt != nullptr) + { + I_BuildMIDIMenuList(*opt); + } + opt = OptionValues.CheckKey(NAME_Aldevices); + if (opt != nullptr) + { + I_BuildALDeviceList(*opt); + } + opt = OptionValues.CheckKey(NAME_Alresamplers); + if (opt != nullptr) + { + I_BuildALResamplersList(*opt); + } +} + +//============================================================================= +// +// Returns the default skill level. +// +//============================================================================= + +int M_GetDefaultSkill() +{ + return gDefaultSkill; +} diff --git a/source/common/menu/menuinput.cpp b/source/common/menu/menuinput.cpp new file mode 100644 index 000000000..95185c072 --- /dev/null +++ b/source/common/menu/menuinput.cpp @@ -0,0 +1,373 @@ +/* +** menuinput.cpp +** The string input code +** +**--------------------------------------------------------------------------- +** Copyright 2001-2010 Randy Heit +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "menu/menu.h" +#include "c_cvars.h" +#include "d_event.h" +#include "d_gui.h" +#include "v_font.h" +#include "v_text.h" +#include "v_draw.h" + +#define INPUTGRID_WIDTH 13 +#define INPUTGRID_HEIGHT 5 + +// Heretic and Hexen do not, by default, come with glyphs for all of these +// characters. Oh well. Doom and Strife do. +static const char InputGridChars[INPUTGRID_WIDTH * INPUTGRID_HEIGHT] = + "ABCDEFGHIJKLM" + "NOPQRSTUVWXYZ" + "0123456789+-=" + ".,!?@'\":;[]()" + "<>^#$%&*/_ \b"; + + +CVAR(Bool, m_showinputgrid, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) + +//============================================================================= +// +// +// +//============================================================================= + +// [TP] Added allowcolors +DTextEnterMenu::DTextEnterMenu(DMenu *parent, FFont *dpf, FString textbuffer, int maxlen, bool showgrid, bool allowcolors) +: DMenu(parent) +{ + mEnterString = textbuffer; + mEnterPos = maxlen; + mInputGridOkay = (showgrid && (m_showinputgrid == 0)) || (m_showinputgrid >= 1); + if (mEnterString.Len() > 0) + { + InputGridX = INPUTGRID_WIDTH - 1; + InputGridY = INPUTGRID_HEIGHT - 1; + } + else + { + // If we are naming a new save, don't start the cursor on "end". + InputGridX = 0; + InputGridY = 0; + } + AllowColors = allowcolors; // [TP] + displayFont = dpf; + CursorSize = displayFont->StringWidth(displayFont->GetCursor()); +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DTextEnterMenu::TranslateKeyboardEvents() +{ + return mInputGridOkay; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DTextEnterMenu::Responder(event_t *ev) +{ + if (ev->type == EV_GUI_Event) + { + // Save game and player name string input + if (ev->subtype == EV_GUI_Char) + { + mInputGridOkay = false; + AppendChar(ev->data1); + return true; + } + char ch = (char)ev->data1; + if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b') + { + if (mEnterPos > 0) + { + mEnterString.DeleteLastCharacter(); + } + } + else if (ev->subtype == EV_GUI_KeyDown) + { + if (ch == GK_ESCAPE) + { + DMenu *parent = mParentMenu; + parent->MenuEvent(MKEY_Abort, false); + Close(); + return true; + } + else if (ch == '\r') + { + if (mEnterString.Len() > 0) + { + // [TP] If we allow color codes, colorize the string now. + //if (AllowColors) + //mEnterString = mEnterString.Filter(); + + DMenu *parent = mParentMenu; + parent->MenuEvent(MKEY_Input, false); + Close(); + return true; + } + } + } + if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) + { + return true; + } + } + return Super::Responder(ev); +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DTextEnterMenu::MouseEvent(int type, int x, int y) +{ + const int cell_width = 18 * CleanXfac_1; + const int cell_height = 16 * CleanYfac_1; + const int screen_y = screen->GetHeight() - INPUTGRID_HEIGHT * cell_height; + const int screen_x = (screen->GetWidth() - INPUTGRID_WIDTH * cell_width) / 2; + + if (x >= screen_x && x < screen_x + INPUTGRID_WIDTH * cell_width && y >= screen_y) + { + InputGridX = (x - screen_x) / cell_width; + InputGridY = (y - screen_y) / cell_height; + if (type == DMenu::MOUSE_Release) + { + if (MenuEvent(MKEY_Enter, true)) + { + //M_MenuSound(CursorSound); + if (m_use_mouse == 2) InputGridX = InputGridY = -1; + } + } + return true; + } + else + { + InputGridX = InputGridY = -1; + } + return Super::MouseEvent(type, x, y); +} + +//============================================================================= +// +// +// +//============================================================================= + +void DTextEnterMenu::AppendChar(int ch) +{ + FStringf newstring("%s%c%c", mEnterString.GetChars(), ch, displayFont->GetCursor()); + if (mEnterSize < 0 || displayFont->StringWidth(newstring) < mEnterSize) + { + mEnterString.AppendCharacter(ch); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DTextEnterMenu::MenuEvent (int key, bool fromcontroller) +{ + if (key == MKEY_Back) + { + mParentMenu->MenuEvent(MKEY_Abort, false); + return Super::MenuEvent(key, fromcontroller); + } + if (fromcontroller) + { + mInputGridOkay = true; + } + + if (mInputGridOkay) + { + int ch; + + if (InputGridX == -1 || InputGridY == -1) + { + InputGridX = InputGridY = 0; + } + switch (key) + { + case MKEY_Down: + InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT; + return true; + + case MKEY_Up: + InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT; + return true; + + case MKEY_Right: + InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH; + return true; + + case MKEY_Left: + InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH; + return true; + + case MKEY_Clear: + if (mEnterString.Len() > 0) + { + mEnterString.DeleteLastCharacter(); + } + return true; + + case MKEY_Enter: + assert(unsigned(InputGridX) < INPUTGRID_WIDTH && unsigned(InputGridY) < INPUTGRID_HEIGHT); + if (mInputGridOkay) + { + ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH]; + if (ch == 0) // end + { + if (mEnterString.Len() > 0) + { + DMenu *parent = mParentMenu; + parent->MenuEvent(MKEY_Input, false); + Close(); + return true; + } + } + else if (ch == '\b') // bs + { + if (mEnterString.Len() > 0) + { + mEnterString.DeleteLastCharacter(); + } + } + else + { + AppendChar(ch); + } + } + return true; + + default: + break; // Keep GCC quiet + } + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +void DTextEnterMenu::Drawer () +{ + mParentMenu->Drawer(); + if (mInputGridOkay) + { + const int cell_width = 18 * CleanXfac; + const int cell_height = 12 * CleanYfac; + const int top_padding = cell_height / 2 - displayFont->GetHeight() * CleanYfac / 2; + + // Darken the background behind the character grid. + // Unless we frame it with a border, I think it looks better to extend the + // background across the full width of the screen. + twod.AddColorOnlyQuad(0 /*screen->GetWidth()/2 - 13 * cell_width / 2*/, + screen->GetHeight() - INPUTGRID_HEIGHT * cell_height, + screen->GetWidth() /*13 * cell_width*/, + INPUTGRID_HEIGHT * cell_height, 0xc8000000); + + if (InputGridX >= 0 && InputGridY >= 0) + { + // Highlight the background behind the selected character. + twod.AddColorOnlyQuad( + InputGridX * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2, + InputGridY * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight(), + cell_width, cell_height, PalEntry(255, 255, 248, 220)); + } + + for (int y = 0; y < INPUTGRID_HEIGHT; ++y) + { + const int yy = y * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight(); + for (int x = 0; x < INPUTGRID_WIDTH; ++x) + { + int width; + const int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2; + const int ch = InputGridChars[y * INPUTGRID_WIDTH + x]; + FTexture *pic = displayFont->GetChar(ch, CR_DARKGRAY, &width); + EColorRange color; + int remap; + + // The highlighted character is yellow; the rest are dark gray. + color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY; + remap = displayFont->GetColorTranslation(color); + + if (pic != NULL) + { + // Draw a normal character. + DrawTexture(&twod, pic, xx + cell_width/2 - width*CleanXfac_1/2, yy + top_padding, + DTA_TranslationIndex, remap, + DTA_CleanNoMove_1, true, + TAG_DONE); + } + else if (ch == ' ') + { + // Draw the space as a box outline. We also draw it 50% wider than it really is. + const int x1 = xx + cell_width/2 - width * CleanXfac_1 * 3 / 4; + const int x2 = x1 + width * 3 * CleanXfac_1 / 2; + const int y1 = yy + top_padding; + const int y2 = y1 + displayFont->GetHeight() * CleanYfac_1; + auto palcolor = PalEntry(255, 160, 160, 160); + twod.AddColorOnlyQuad(x1, y1, x2 - x1, CleanYfac_1, palcolor); // top + twod.AddColorOnlyQuad(x1, y2, x2 - x1, CleanYfac_1, palcolor); // bottom + twod.AddColorOnlyQuad(x1, y1+CleanYfac_1, CleanXfac_1, y2 - y1, palcolor); // left + twod.AddColorOnlyQuad(x2-CleanXfac_1, y1+CleanYfac_1, CleanXfac_1, CleanYfac_1, palcolor); // right + } + else if (ch == '\b' || ch == 0) + { + // Draw the backspace and end "characters". + const char *const str = ch == '\b' ? "BS" : "ED"; + DrawText(&twod, NewSmallFont, color, + xx + cell_width/2 - displayFont->StringWidth(str)*CleanXfac_1/2, + yy + top_padding, str, DTA_CleanNoMove_1, true, TAG_DONE); + } + } + } + } + Super::Drawer(); +} \ No newline at end of file diff --git a/source/common/menu/messagebox.cpp b/source/common/menu/messagebox.cpp new file mode 100644 index 000000000..134358930 --- /dev/null +++ b/source/common/menu/messagebox.cpp @@ -0,0 +1,441 @@ +/* +** messagebox.cpp +** Confirmation, notification screns +** +**--------------------------------------------------------------------------- +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "menu.h" +#include "d_event.h" +#include "d_gui.h" +#include "v_text.h" +#include "v_draw.h" +#include "gstrings.h" +#include "c_dispatch.h" +#include "statistics.h" +#include "v_2ddrawer.h" + +extern FSaveGameNode *quickSaveSlot; + +class DMessageBoxMenu : public DMenu +{ + using Super = DMenu; + FString mFullMessage; + TArray mMessage; + int mMessageMode; + int messageSelection; + int mMouseLeft, mMouseRight, mMouseY; + FName mAction; + std::function mActionFunc; + +public: + + DMessageBoxMenu(DMenu *parent = NULL, const char *message = NULL, int messagemode = 0, bool playsound = false, FName action = NAME_None, hFunc handler = nullptr); + void Destroy(); + void Init(DMenu *parent, const char *message, int messagemode, bool playsound = false); + void Drawer(); + bool Responder(event_t *ev); + bool MenuEvent(int mkey, bool fromcontroller); + bool MouseEvent(int type, int x, int y); + void CloseSound(); + virtual void HandleResult(bool res); +}; + + +//============================================================================= +// +// +// +//============================================================================= + +DMessageBoxMenu::DMessageBoxMenu(DMenu *parent, const char *message, int messagemode, bool playsound, FName action, hFunc handler) +: DMenu(parent) +{ + mAction = action; + mActionFunc = handler; + messageSelection = 0; + mMouseLeft = 140; + mMouseY = INT_MIN; + int mr1 = 170 + SmallFont->StringWidth(GStrings["TXT_YES"]); + int mr2 = 170 + SmallFont->StringWidth(GStrings["TXT_NO"]); + mMouseRight = std::max(mr1, mr2); + + Init(parent, message, messagemode, playsound); +} + +//============================================================================= +// +// +// +//============================================================================= + +void DMessageBoxMenu::Init(DMenu *parent, const char *message, int messagemode, bool playsound) +{ + mParentMenu = parent; + if (message != NULL) + { + mFullMessage = message; + mMessage = V_BreakLines(SmallFont, 300, GStrings.localize(message)); + } + mMessageMode = messagemode; + if (playsound) + { + //S_StopSound (CHAN_VOICE); + //S_Sound (CHAN_VOICE | CHAN_UI, "menu/prompt", snd_menuvolume, ATTN_NONE); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +void DMessageBoxMenu::Destroy() +{ + mMessage.Reset(); +} + +//============================================================================= +// +// +// +//============================================================================= + +void DMessageBoxMenu::CloseSound() +{ + M_MenuSound(DMenu::CurrentMenu ? BackSound : ::CloseSound); +} + +//============================================================================= +// +// +// +//============================================================================= + +void DMessageBoxMenu::HandleResult(bool res) +{ + if (mParentMenu != NULL) + { + if (mMessageMode == 0) + { + if (mActionFunc) + { + mActionFunc(res); + Close(); + } + else if (mAction == NAME_None) + { + mParentMenu->MenuEvent(res? MKEY_MBYes : MKEY_MBNo, false); + Close(); + } + else + { + Close(); + if (res) M_SetMenu(mAction, -1); + } + CloseSound(); + } + } +} + +//============================================================================= +// +// +// +//============================================================================= +CVAR(Bool, m_generic_messagebox, false, CVAR_ARCHIVE) + +void DMessageBoxMenu::Drawer() +{ + int y; + PalEntry fade = 0; + + int fontheight = SmallFont->GetHeight(); + //V_SetBorderNeedRefresh(); + //ST_SetNeedRefresh(); + + y = 100; + + if (m_generic_messagebox) + { + if (mMessage.Size()) + { + for (unsigned i = 0; i < mMessage.Size(); i++) + y -= SmallFont->GetHeight() / 2; + + for (unsigned i = 0; i < mMessage.Size(); i++) + { + DrawText(&twod, SmallFont, CR_UNTRANSLATED, 160 - mMessage[i].Width / 2, y, mMessage[i].Text, + DTA_Clean, true, TAG_DONE); + y += fontheight; + } + } + + if (mMessageMode == 0) + { + y += fontheight; + mMouseY = y; + DrawText(&twod, NewSmallFont, + messageSelection == 0 ? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, + 160, y, GStrings["TXT_YES"], DTA_Clean, true, TAG_DONE); + DrawText(&twod, NewSmallFont, + messageSelection == 1 ? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, + 160, y + fontheight + 1, GStrings["TXT_NO"], DTA_Clean, true, TAG_DONE); + + if (messageSelection >= 0) + { + if (((DMenu::MenuTime >> 2) % 8) < 6) + { + DrawText(&twod, NewSmallFont, OptionSettings.mFontColorSelection, + (150 - 160) * CleanXfac + screen->GetWidth() / 2, + (y + (fontheight + 1) * messageSelection - 100 + fontheight / 2 - 5) * CleanYfac + screen->GetHeight() / 2, + "\xd", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac, + TAG_DONE); + } + } + } + } + else + { + twod.AddColorOnlyQuad(0, 0, xdim, ydim, 0xa0000000); + gi->DrawCenteredTextScreen(origin, mFullMessage, 100, false); + } +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DMessageBoxMenu::Responder(event_t *ev) +{ + if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown) + { + if (mMessageMode == 0) + { + int ch = tolower(ev->data1); + if (ch == 'n' || ch == ' ') + { + HandleResult(false); + return true; + } + else if (ch == 'y') + { + HandleResult(true); + return true; + } + } + else + { + Close(); + return true; + } + return false; + } + else if (ev->type == EV_KeyDown) + { + Close(); + return true; + } + return Super::Responder(ev); +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DMessageBoxMenu::MenuEvent(int mkey, bool fromcontroller) +{ + if (mMessageMode == 0) + { + if ((mkey == MKEY_Up || mkey == MKEY_Down) && m_generic_messagebox) + { + //S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); + messageSelection = !messageSelection; + return true; + } + else if (mkey == MKEY_Enter) + { + // 0 is yes, 1 is no + HandleResult(!messageSelection); + return true; + } + else if (mkey == MKEY_Back) + { + HandleResult(false); + return true; + } + return false; + } + else + { + Close(); + CloseSound(); + return true; + } +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DMessageBoxMenu::MouseEvent(int type, int x, int y) +{ + if (mMessageMode == 1 || m_generic_messagebox) + { + if (type == MOUSE_Click) + { + return MenuEvent(MKEY_Enter, true); + } + return false; + } + else + { + int sel = -1; + int fh = SmallFont->GetHeight() + 1; + + // convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture + x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160; + y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100; + + if (x >= mMouseLeft && x <= mMouseRight && y >= mMouseY && y < mMouseY + 2 * fh) + { + sel = y >= mMouseY + fh; + } + if (sel != -1 && sel != messageSelection) + { + gi->MenuSound(CursorSound); + } + messageSelection = sel; + if (type == MOUSE_Release) + { + return MenuEvent(MKEY_Enter, true); + } + return true; + } +} + +//============================================================================= +// +// +// +//============================================================================= + +//============================================================================= +// +// +// +//============================================================================= + +void M_StartMessage(const char *message, int messagemode, int scriptId, FName action) +{ + if (DMenu::CurrentMenu == NULL) + { + // only play a sound if no menu was active before + M_StartControlPanel(menuactive == MENU_Off); + } + DMenu *newmenu = new DMessageBoxMenu(DMenu::CurrentMenu, message, messagemode, false, action); + newmenu->mParentMenu = DMenu::CurrentMenu; + newmenu->scriptID = scriptId; + M_ActivateMenu(newmenu); +} + + +//============================================================================= +// +// +// +//============================================================================= + +DMenu* CreateMessageBoxMenu(DMenu* parent, const char* message, int messagemode, int scriptId, bool playsound, FName action, hFunc handler) +{ + auto newmenu = new DMessageBoxMenu(DMenu::CurrentMenu, message, messagemode, false, action, handler); + newmenu->scriptID = scriptId; + return newmenu; + +} + + +void ActivateEndGameMenu() +{ +} + +CCMD (menu_endgame) +{ // F7 + if (!gi->CanSave()) + { + return; + } + + M_StartControlPanel (true); + FString tempstring = GStrings("ENDGAME"); + DMenu* newmenu = CreateMessageBoxMenu(DMenu::CurrentMenu, tempstring, 0, 501, false, NAME_None, [](bool res) + { + if (res) + { + STAT_Cancel(); + gi->QuitToTitle(); + } + }); + + M_ActivateMenu(newmenu); +} + +//============================================================================= +// +// +// +//============================================================================= + +CCMD (menu_quit) +{ // F10 + + M_StartControlPanel (true); + + FString EndString = GStrings("CONFIRM_QUITMSG"); + EndString << "\n[Y/N]"; + + DMenu *newmenu = CreateMessageBoxMenu(DMenu::CurrentMenu, EndString, 0, 500, false, NAME_None, [](bool res) + { + if (res) throw ExitEvent(0); + }); + + M_ActivateMenu(newmenu); +} + + diff --git a/source/common/menu/optionmenu.cpp b/source/common/menu/optionmenu.cpp new file mode 100644 index 000000000..c5e1d5f14 --- /dev/null +++ b/source/common/menu/optionmenu.cpp @@ -0,0 +1,561 @@ +/* +** optionmenu.cpp +** Handler class for the option menus and associated items +** +**--------------------------------------------------------------------------- +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "v_font.h" +#include "cmdlib.h" +#include "gstrings.h" +#include "d_gui.h" +#include "d_event.h" +#include "c_dispatch.h" +#include "c_console.h" +#include "c_cvars.h" +#include "c_bind.h" +#include "gameconfigfile.h" +#include "menu/menu.h" +#include "v_draw.h" +#include "v_2ddrawer.h" + +//============================================================================= +// +// Draws a string in the console font, scaled to the 8x8 cells +// used by the default console font. +// +//============================================================================= + +FFont *OptionFont() +{ + return NewSmallFont; +} + +int OptionHeight() +{ + return OptionFont()->GetHeight(); +} + +int OptionWidth(const char * s) +{ + return OptionFont()->StringWidth(s); +} + +void DrawOptionText(int x, int y, int color, const char *text, bool grayed) +{ + PalEntry overlay = grayed? PalEntry(96,48,0,0) : PalEntry(0,0,0); + DrawText (&twod, OptionFont(), color, x, y, text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, TAG_END); +} + +//============================================================================= +// +// +// +//============================================================================= + +DOptionMenu::DOptionMenu(DMenu *parent, FOptionMenuDescriptor *desc) +: DMenu(parent) +{ + CanScrollUp = false; + CanScrollDown = false; + VisBottom = 0; + mFocusControl = NULL; + Init(parent, desc); +} + +//============================================================================= +// +// +// +//============================================================================= + +void DOptionMenu::Init(DMenu *parent, FOptionMenuDescriptor *desc) +{ + mParentMenu = parent; + mDesc = desc; + if (mDesc != NULL && mDesc->mSelectedItem == -1) mDesc->mSelectedItem = FirstSelectable(); + +} + +//============================================================================= +// +// +// +//============================================================================= + +int DOptionMenu::FirstSelectable() +{ + if (mDesc != NULL) + { + // Go down to the first selectable item + int i = -1; + do + { + i++; + } + while (i < (int)mDesc->mItems.Size() && !mDesc->mItems[i]->Selectable()); + if (i>=0 && i < (int)mDesc->mItems.Size()) return i; + } + return -1; +} + +//============================================================================= +// +// +// +//============================================================================= + +FOptionMenuItem *DOptionMenu::GetItem(FName name) +{ + for(unsigned i=0;imItems.Size(); i++) + { + FName nm = mDesc->mItems[i]->GetAction(NULL); + if (nm == name) return mDesc->mItems[i]; + } + return NULL; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DOptionMenu::Responder (event_t *ev) +{ + if (ev->type == EV_GUI_Event) + { + if (ev->subtype == EV_GUI_WheelUp) + { + int scrollamt = std::min(2, mDesc->mScrollPos); + mDesc->mScrollPos -= scrollamt; + return true; + } + else if (ev->subtype == EV_GUI_WheelDown) + { + if (CanScrollDown) + { + if (VisBottom < (int)(mDesc->mItems.Size()-2)) + { + mDesc->mScrollPos += 2; + VisBottom += 2; + } + else + { + mDesc->mScrollPos++; + VisBottom++; + } + } + return true; + } + } + return Super::Responder(ev); +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DOptionMenu::MenuEvent (int mkey, bool fromcontroller) +{ + int startedAt = mDesc->mSelectedItem; + + switch (mkey) + { + case MKEY_Up: + if (mDesc->mSelectedItem == -1) + { + mDesc->mSelectedItem = FirstSelectable(); + break; + } + do + { + --mDesc->mSelectedItem; + + if (mDesc->mScrollPos > 0 && + mDesc->mSelectedItem <= mDesc->mScrollTop + mDesc->mScrollPos) + { + mDesc->mScrollPos = std::max(mDesc->mSelectedItem - mDesc->mScrollTop - 1, 0); + } + + if (mDesc->mSelectedItem < 0) + { + // Figure out how many lines of text fit on the menu + int y = mDesc->mPosition; + + y *= CleanYfac_1; + int rowheight = OptionSettings.mLinespacing * CleanYfac_1; + int maxitems = (screen->GetHeight() - rowheight - y) / rowheight + 1; + + mDesc->mScrollPos = std::max(0, (int)mDesc->mItems.Size() - maxitems + mDesc->mScrollTop); + mDesc->mSelectedItem = mDesc->mItems.Size()-1; + } + } + while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt); + break; + + case MKEY_Down: + if (mDesc->mSelectedItem == -1) + { + mDesc->mSelectedItem = FirstSelectable(); + break; + } + do + { + ++mDesc->mSelectedItem; + + if (CanScrollDown && mDesc->mSelectedItem == VisBottom) + { + mDesc->mScrollPos++; + VisBottom++; + } + if (mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) + { + if (startedAt == -1) + { + mDesc->mSelectedItem = -1; + mDesc->mScrollPos = -1; + break; + } + else + { + mDesc->mSelectedItem = 0; + mDesc->mScrollPos = 0; + } + } + } + while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable() && mDesc->mSelectedItem != startedAt); + break; + + case MKEY_PageUp: + if (mDesc->mScrollPos > 0) + { + mDesc->mScrollPos -= VisBottom - mDesc->mScrollPos - mDesc->mScrollTop; + if (mDesc->mScrollPos < 0) + { + mDesc->mScrollPos = 0; + } + if (mDesc->mSelectedItem != -1) + { + mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos + 1; + while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable()) + { + if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) + { + mDesc->mSelectedItem = 0; + } + } + if (mDesc->mScrollPos > mDesc->mSelectedItem) + { + mDesc->mScrollPos = mDesc->mSelectedItem; + } + } + } + break; + + case MKEY_PageDown: + if (CanScrollDown) + { + int pagesize = VisBottom - mDesc->mScrollPos - mDesc->mScrollTop; + mDesc->mScrollPos += pagesize; + if (mDesc->mScrollPos + mDesc->mScrollTop + pagesize > (int)mDesc->mItems.Size()) + { + mDesc->mScrollPos = mDesc->mItems.Size() - mDesc->mScrollTop - pagesize; + } + if (mDesc->mSelectedItem != -1) + { + mDesc->mSelectedItem = mDesc->mScrollTop + mDesc->mScrollPos; + while (!mDesc->mItems[mDesc->mSelectedItem]->Selectable()) + { + if (++mDesc->mSelectedItem >= (int)mDesc->mItems.Size()) + { + mDesc->mSelectedItem = 0; + } + } + if (mDesc->mScrollPos > mDesc->mSelectedItem) + { + mDesc->mScrollPos = mDesc->mSelectedItem; + } + } + } + break; + + case MKEY_Enter: + if (mDesc->mSelectedItem >= 0 && mDesc->mItems[mDesc->mSelectedItem]->Activate(mDesc->mMenuName)) + { + return true; + } + // fall through to default + default: + if (mDesc->mSelectedItem >= 0 && + mDesc->mItems[mDesc->mSelectedItem]->MenuEvent(mkey, fromcontroller)) return true; + return Super::MenuEvent(mkey, fromcontroller); + } + + if (mDesc->mSelectedItem != startedAt) + { + M_MenuSound(CursorSound); + } + return true; +} + +//============================================================================= +// +// +// +//============================================================================= + +bool DOptionMenu::MouseEvent(int type, int x, int y) +{ + y = (y / CleanYfac_1) - mDesc->mDrawTop; + + if (mFocusControl) + { + mFocusControl->MouseEvent(type, x, y); + return true; + } + else + { + int yline = (y / OptionSettings.mLinespacing); + if (yline >= mDesc->mScrollTop) + { + yline += mDesc->mScrollPos; + } + if ((unsigned)yline < mDesc->mItems.Size() && mDesc->mItems[yline]->Selectable()) + { + if (yline != mDesc->mSelectedItem) + { + mDesc->mSelectedItem = yline; + //M_MenuSound(CursorSound); too noisy + + } + mDesc->mItems[yline]->MouseEvent(type, x, y); + return true; + } + } + mDesc->mSelectedItem = -1; + return Super::MouseEvent(type, x, y); +} + +//============================================================================= +// +// +// +//============================================================================= + +void DOptionMenu::Ticker () +{ + Super::Ticker(); + for(unsigned i=0;imItems.Size(); i++) + { + mDesc->mItems[i]->Ticker(); + } +} + +//============================================================================= +// +// +// +//============================================================================= +int DOptionMenu::GetIndent() +{ + int indent = std::max(0, (mDesc->mIndent + 40) - CleanWidth_1 / 2); + return screen->GetWidth() / 2 + indent * CleanXfac_1; +} + +void DOptionMenu::Drawer () +{ + int y = mDesc->mPosition; + + if (mDesc->mTitle.IsNotEmpty()) + { + gi->DrawMenuCaption(origin, GStrings.localize(mDesc->mTitle)); + } + mDesc->mDrawTop = y; + int fontheight = OptionSettings.mLinespacing * CleanYfac_1; + y *= CleanYfac_1; + + int indent = GetIndent(); + + int ytop = y + mDesc->mScrollTop * 8 * CleanYfac_1; + int lastrow = screen->GetHeight() - OptionFont()->GetHeight() * CleanYfac_1; + + unsigned i; + for (i = 0; i < mDesc->mItems.Size() && y <= lastrow; i++, y += fontheight) + { + // Don't scroll the uppermost items + if ((int)i == mDesc->mScrollTop) + { + i += mDesc->mScrollPos; + if (i >= mDesc->mItems.Size()) break; // skipped beyond end of menu + } + bool isSelected = mDesc->mSelectedItem == (int)i; + int cur_indent = mDesc->mItems[i]->Draw(mDesc, y, indent, isSelected); + if (cur_indent >= 0 && isSelected && mDesc->mItems[i]->Selectable()) + { + if ((((DMenu::MenuTime>>2)%8) < 6) || DMenu::CurrentMenu != this) + { + DrawOptionText(cur_indent + 3 * CleanXfac_1, y, OptionSettings.mFontColorSelection, "â—„"); + //M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd"); + } + } + } + + CanScrollUp = (mDesc->mScrollPos > 0); + CanScrollDown = (i < mDesc->mItems.Size()); + VisBottom = i - 1; + + if (CanScrollUp) + { + DrawOptionText(screen->GetWidth() - 11 * CleanXfac_1, ytop, OptionSettings.mFontColorSelection, "â–²"); + //M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, ytop, "\x1a"); + } + if (CanScrollDown) + { + DrawOptionText(screen->GetWidth() - 11 * CleanXfac_1 , y - 8*CleanYfac_1, OptionSettings.mFontColorSelection, "â–¼"); + //M_DrawConText(CR_ORANGE, 3 * CleanXfac_1, y - 8*CleanYfac_1, "\x1b"); + } + Super::Drawer(); +} + + +//============================================================================= +// +// base class for menu items +// +//============================================================================= + +FOptionMenuItem::~FOptionMenuItem() +{ +} + +int FOptionMenuItem::Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) +{ + return indent; +} + +bool FOptionMenuItem::Selectable() +{ + return true; +} + +bool FOptionMenuItem::MouseEvent(int type, int x, int y) +{ + if (Selectable() && type == DMenu::MOUSE_Release) + { + return DMenu::CurrentMenu->MenuEvent(MKEY_Enter, true); + } + return false; +} + + +int FOptionMenuItem::GetIndent() +{ + if (mCentered) return 0; + if (screen->GetWidth() < 640) return screen->GetWidth() / 2; + return OptionWidth(GStrings.localize(mLabel)); +} + +void FOptionMenuItem::drawText(int x, int y, int color, const char * text, bool grayed) +{ + DrawOptionText(x, y, color, text, grayed); +} + +int FOptionMenuItem::drawLabel(int indent, int y, EColorRange color, bool grayed) +{ + const char *label = GStrings.localize(mLabel); + int x; + int w = OptionWidth(label) * CleanXfac_1; + if (!mCentered) x = indent - w; + else x = (screen->GetWidth() - w) / 2; + DrawOptionText(x, y, color, label, grayed); + return x; +} + +void FOptionMenuItem::drawValue(int indent, int y, int color, const char *text, bool grayed) +{ + DrawOptionText(indent + CursorSpace(), y, color, text, grayed); +} + +int FOptionMenuItem::CursorSpace() +{ + return (14 * CleanXfac_1); +} + +void FOptionMenuDescriptor::CalcIndent() +{ + // calculate the menu indent + int widest = 0, thiswidth; + + for (unsigned i = 0; i < mItems.Size(); i++) + { + thiswidth = mItems[i]->GetIndent(); + if (thiswidth > widest) widest = thiswidth; + } + mIndent = widest + 4; +} + +//============================================================================= +// +// +// +//============================================================================= + +FOptionMenuItem *FOptionMenuDescriptor::GetItem(FName name) +{ + for(unsigned i=0;iGetAction(NULL); + if (nm == name) return mItems[i]; + } + return NULL; +} + +class PlayerMenu : public DOptionMenu +{ + using Super = DOptionMenu; + +public: + void Drawer() + { + // Hack: The team item is #3. This part doesn't work properly yet. + gi->DrawPlayerSprite(origin, (mDesc->mSelectedItem == 3)); + Super::Drawer(); + } +}; + +static TMenuClassDescriptor _ppm("NewPlayerMenu"); + +void RegisterOptionMenus() +{ + menuClasses.Push(&_ppm); +} diff --git a/source/common/menu/optionmenuitems.h b/source/common/menu/optionmenuitems.h new file mode 100644 index 000000000..8df332b8f --- /dev/null +++ b/source/common/menu/optionmenuitems.h @@ -0,0 +1,998 @@ +/* +** optionmenuitems.h +** Control items for option menus +** +**--------------------------------------------------------------------------- +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ +#include "v_text.h" +#include "v_draw.h" +#include "gstrings.h" +#include "v_font.h" + + +void M_DrawConText (int color, int x, int y, const char *str); +void M_SetVideoMode(); + + + +//============================================================================= +// +// opens a submenu, action is a submenu name +// +//============================================================================= + +class FOptionMenuItemSubmenu : public FOptionMenuItem +{ + int mParam; +public: + FOptionMenuItemSubmenu(const char *label, const char *menu, int param = 0) + : FOptionMenuItem(label, menu) + { + mParam = param; + } + + int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) override + { + drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColorMore); + return indent; + } + + bool Activate(FName caller) override + { + M_MenuSound(CursorSound); + M_SetMenu(mAction, mParam); + return true; + } +}; + + +//============================================================================= +// +// opens a submenu, command is a submenu name +// +//============================================================================= + +class FOptionMenuItemLabeledSubmenu : public FOptionMenuItemSubmenu +{ + FBaseCVar *mLabelCVar; +public: + FOptionMenuItemLabeledSubmenu(const char * label, FBaseCVar *labelcvar, FName command, int param = 0) + : FOptionMenuItemSubmenu(label, command, param) + { + mLabelCVar = labelcvar; + } + + int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) override + { + drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor); + + auto text = mLabelCVar? mLabelCVar->GetHumanString() : ""; + if (text[0] == 0) text = GStrings("notset"); + drawValue(indent, y, OptionSettings.mFontColorValue, text); + return indent; + } +}; + + +//============================================================================= +// +// Executes a CCMD, action is a CCMD name +// +//============================================================================= + +class FOptionMenuItemCommand : public FOptionMenuItemSubmenu +{ +public: + FOptionMenuItemCommand(const char *label, const char *menu) + : FOptionMenuItemSubmenu(label, menu) + { + } + + bool Activate(FName caller) override + { + M_MenuSound(AdvanceSound); + C_DoCommand(mAction); + return true; + } + +}; + +//============================================================================= +// +// Executes a CCMD after confirmation, action is a CCMD name +// +//============================================================================= + +class FOptionMenuItemSafeCommand : public FOptionMenuItemCommand +{ + // action is a CCMD + FString mPrompt; + int mScriptId; // shouldn't be used, but just in case. +public: + FOptionMenuItemSafeCommand(const char *label, const char *menu, const char *prompt = nullptr, int scriptid = INT_MAX) + : FOptionMenuItemCommand(label, menu) + { + mPrompt = prompt; + mScriptId = scriptid; + } + + bool MenuEvent (int mkey, bool fromcontroller) override + { + if (mkey == MKEY_MBYes) + { + C_DoCommand(mAction); + return true; + } + return FOptionMenuItemCommand::MenuEvent(mkey, fromcontroller); + } + + bool Activate(FName caller) override + { + auto msg = GStrings.localize(mPrompt.IsNotEmpty()? mPrompt.GetChars() : "$SAFEMESSAGE"); + auto actionLabel = GStrings.localize(mLabel.GetChars()); + + FStringf FullString("%s%s%s\n\n%s", TEXTCOLOR_WHITE, actionLabel, TEXTCOLOR_NORMAL, msg); + M_StartMessage(FullString, 0, mScriptId); + return true; + } +}; + +//============================================================================= +// +// Base class for option lists +// +//============================================================================= + +class FOptionMenuItemOptionBase : public FOptionMenuItem +{ +protected: + // action is a CVAR + FName mValues; // Entry in OptionValues table + FBaseCVar *mGrayCheck; + int mCenter; +public: + + enum + { + OP_VALUES = 0x11001 + }; + + FOptionMenuItemOptionBase(const char *label, const char *menu, const char *values, const char *graycheck, int center) + : FOptionMenuItem(label, menu) + { + mValues = values; + mGrayCheck = (FBoolCVar*)FindCVar(graycheck, NULL); + mCenter = center; + } + + bool SetString(int i, const char *newtext) override + { + if (i == OP_VALUES) + { + FOptionValues **opt = OptionValues.CheckKey(newtext); + mValues = newtext; + if (opt != NULL && *opt != NULL) + { + int s = GetSelection(); + if (s >= (int)(*opt)->mValues.Size()) s = 0; + SetSelection(s); // readjust the CVAR if its value is outside the range now + return true; + } + } + return false; + } + + + + //============================================================================= + virtual int GetSelection() = 0; + virtual void SetSelection(int Selection) = 0; + + //============================================================================= + int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) override + { + if (mCenter) + { + indent = (screen->GetWidth() / 2); + } + drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, isGrayed()); + + int Selection = GetSelection(); + const char *text; + FOptionValues **opt = OptionValues.CheckKey(mValues); + if (Selection < 0 || opt == NULL || *opt == NULL) + { + text = "Unknown"; + } + else + { + text = (*opt)->mValues[Selection].Text; + } + if (*text == '$') text = GStrings(text + 1); + + drawValue(indent, y, OptionSettings.mFontColorValue, text, isGrayed()); + return indent; + } + + //============================================================================= + bool MenuEvent (int mkey, bool fromcontroller) override + { + FOptionValues **opt = OptionValues.CheckKey(mValues); + if (opt != NULL && *opt != NULL && (*opt)->mValues.Size() > 0) + { + int Selection = GetSelection(); + if (mkey == MKEY_Left) + { + if (Selection == -1) Selection = 0; + else if (--Selection < 0) Selection = (*opt)->mValues.Size()-1; + } + else if (mkey == MKEY_Right || mkey == MKEY_Enter) + { + if (++Selection >= (int)(*opt)->mValues.Size()) Selection = 0; + } + else + { + return FOptionMenuItem::MenuEvent(mkey, fromcontroller); + } + SetSelection(Selection); + M_MenuSound(ChangeSound); + } + return true; + } + + virtual bool isGrayed() + { + return mGrayCheck != NULL && !(mGrayCheck->GetGenericRep(CVAR_Bool).Bool); + } + + bool Selectable() override + { + return !isGrayed(); + } +}; + +//============================================================================= +// +// Change a CVAR, action is the CVAR name +// +//============================================================================= + +class FOptionMenuItemOption : public FOptionMenuItemOptionBase +{ + // action is a CVAR + FBaseCVar *mCVar; +public: + + FOptionMenuItemOption(const char *label, const char *menu, const char *values, const char *graycheck, int center) + : FOptionMenuItemOptionBase(label, menu, values, graycheck, center) + { + mCVar = FindCVar(mAction, NULL); + } + + //============================================================================= + int GetSelection() override + { + int Selection = -1; + FOptionValues **opt = OptionValues.CheckKey(mValues); + if (opt != NULL && *opt != NULL && mCVar != NULL && (*opt)->mValues.Size() > 0) + { + if ((*opt)->mValues[0].TextValue.IsEmpty()) + { + UCVarValue cv = mCVar->GetGenericRep(CVAR_Float); + for(unsigned i = 0; i < (*opt)->mValues.Size(); i++) + { + if (fabs(cv.Float - (*opt)->mValues[i].Value) < FLT_EPSILON) + { + Selection = i; + break; + } + } + } + else + { + UCVarValue cv = mCVar->GetGenericRep(CVAR_String); + for(unsigned i = 0; i < (*opt)->mValues.Size(); i++) + { + if ((*opt)->mValues[i].TextValue.CompareNoCase(cv.String) == 0) + { + Selection = i; + break; + } + } + } + } + return Selection; + } + + void SetSelection(int Selection) override + { + UCVarValue value; + FOptionValues **opt = OptionValues.CheckKey(mValues); + if (opt != NULL && *opt != NULL && mCVar != NULL && (*opt)->mValues.Size() > 0) + { + if ((*opt)->mValues[0].TextValue.IsEmpty()) + { + value.Float = (float)(*opt)->mValues[Selection].Value; + mCVar->SetGenericRep (value, CVAR_Float); + } + else + { + value.String = (*opt)->mValues[Selection].TextValue.LockBuffer(); + mCVar->SetGenericRep (value, CVAR_String); + (*opt)->mValues[Selection].TextValue.UnlockBuffer(); + } + } + } +}; + +//============================================================================= +// +// This class is used to capture the key to be used as the new key binding +// for a control item +// +//============================================================================= + +class DEnterKey : public DMenu +{ + int *pKey; + +public: + DEnterKey(DMenu *parent, int *keyptr) + : DMenu(parent) + { + pKey = keyptr; + SetMenuMessage(1); + menuactive = MENU_WaitKey; // There should be a better way to disable GUI capture... + mouseGrabInput(true); + } + + bool TranslateKeyboardEvents() override + { + return false; + } + + void SetMenuMessage(int which) + { + DOptionMenu *m = static_cast(mParentMenu); + if (m) + { + FListMenuItem *it = m->GetItem(NAME_Controlmessage); + if (it != NULL) + { + it->SetValue(0, which); + } + } + } + + bool Responder(event_t *ev) override + { + if (ev->type == EV_KeyDown) + { + *pKey = ev->data1; + menuactive = MENU_On; + mouseGrabInput(false); + SetMenuMessage(0); + auto p = mParentMenu; + Close(); + p->MenuEvent((ev->data1 == KEY_ESCAPE)? MKEY_Abort : MKEY_Input, 0); + return true; + } + return false; + } + + void Drawer() override + { + mParentMenu->Drawer(); + } +}; + +//============================================================================= +// +// // Edit a key binding, Action is the CCMD to bind +// +//============================================================================= + +class FOptionMenuItemControl : public FOptionMenuItem +{ + FKeyBindings *mBindings; + int mInput; + bool mWaiting; +public: + + FOptionMenuItemControl(const char *label, const char *menu, FKeyBindings *bindings) + : FOptionMenuItem(label, menu) + { + mBindings = bindings; + mWaiting = false; + } + + + //============================================================================= + int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) override + { + drawLabel(indent, y, mWaiting? OptionSettings.mFontColorHighlight: + (selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor)); + + auto binds = mBindings->GetKeysForCommand(mAction); + auto description = C_NameKeys(binds.Data(), binds.Size()); + + if (description.Len() > 0) + { + drawValue(indent, y, CR_WHITE, description); + } + else + { + drawValue(indent, y, CR_BLACK, "---"); + } + return indent; + } + + //============================================================================= + bool MenuEvent(int mkey, bool fromcontroller) override + { + if (mkey == MKEY_Input) + { + mWaiting = false; + mBindings->SetBind(mInput, mAction); + return true; + } + else if (mkey == MKEY_Clear) + { + mBindings->UnbindACommand(mAction); + return true; + } + else if (mkey == MKEY_Abort) + { + mWaiting = false; + return true; + } + return false; + } + + bool Activate(FName caller) override + { + M_MenuSound(AdvanceSound); + mWaiting = true; + DMenu *input = new DEnterKey(DMenu::CurrentMenu, &mInput); + M_ActivateMenu(input); + return true; + } +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuItemStaticText : public FOptionMenuItem +{ + EColorRange mColor; +public: + FOptionMenuItemStaticText(const char *label, EColorRange color = CR_UNDEFINED) + : FOptionMenuItem(label, NAME_None, true) + { + mColor = color == CR_UNDEFINED? (EColorRange)OptionSettings.mFontColor : color; + } + + int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) override + { + drawLabel(indent, y, mColor); + return -1; + } + + bool Selectable() override + { + return false; + } + +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuItemStaticTextSwitchable : public FOptionMenuItem +{ + EColorRange mColor; + FString mAltText; + int mCurrent; + +public: + FOptionMenuItemStaticTextSwitchable(const char *label, const char *label2, FName action, EColorRange color = CR_UNDEFINED) + : FOptionMenuItem(label, action, true) + { + mColor = color == CR_UNDEFINED? (EColorRange)OptionSettings.mFontColor : color; + mAltText = label2; + mCurrent = 0; + } + + int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) override + { + const char *txt = GStrings.localize(mCurrent? mAltText.GetChars() : mLabel.GetChars()); + int w = OptionWidth(txt) * CleanXfac_1; + int x = (screen->GetWidth() - w) / 2; + drawText(x, y, mColor, txt); + return -1; + } + + bool SetValue(int i, int val) override + { + if (i == 0) + { + mCurrent = val; + return true; + } + return false; + } + + bool SetString(int i, const char *newtext) override + { + if (i == 0) + { + mAltText = newtext; + return true; + } + return false; + } + + bool Selectable() override + { + return false; + } +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuSliderBase : public FOptionMenuItem +{ + // action is a CVAR + double mMin, mMax, mStep; + int mShowValue; + int mDrawX; + int mSliderShort; + +public: + FOptionMenuSliderBase(const char *label, double min, double max, double step, int showval, FName command = NAME_None) + : FOptionMenuItem(label, command) + { + mMin = min; + mMax = max; + mStep = step; + mShowValue = showval; + mDrawX = 0; + mSliderShort = 0; + } + + virtual double GetSliderValue() = 0; + virtual void SetSliderValue(double val) = 0; + + //============================================================================= + // + // Draw a slider. Set fracdigits negative to not display the current value numerically. + // + //============================================================================= + + void DrawSliderElement (int color, int x, int y, const char * str) + { + DrawText (&twod, ConFont, color, x, y, str, DTA_CellX, 16 * CleanXfac_1, DTA_CellY, 16 * CleanYfac_1, TAG_DONE); + } + + void DrawSlider (int x, int y, double min, double max, double cur, int fracdigits, int indent) + { + char textbuf[16]; + double range; + int maxlen = 0; + int right = x + (12*16 + 4) * CleanXfac_1; + int cy = y;// +(OptionSettings.mLinespacing - 8) * CleanYfac_1; + + range = max - min; + double ccur = clamp(cur, min, max) - min; + + if (fracdigits >= 0) + { + snprintf(textbuf, countof(textbuf), "%.*f", fracdigits, max); + maxlen = NewSmallFont->StringWidth(textbuf) * CleanXfac_1; + } + + mSliderShort = right + maxlen > screen->GetWidth(); + + if (!mSliderShort) + { + DrawSliderElement(CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12"); + DrawSliderElement(CR_ORANGE, x + int((5 + ((ccur * 78) / range)) * CleanXfac_1), cy, "\x13"); + } + else + { + // On 320x200 we need a shorter slider + DrawSliderElement(CR_WHITE, x, cy, "\x10\x11\x11\x11\x11\x11\x12"); + DrawSliderElement(CR_ORANGE, x + int((5 + ((ccur * 38) / range)) * CleanXfac_1), cy, "\x13"); + right -= 5*8*CleanXfac_1; + } + + if (fracdigits >= 0 && right + maxlen <= screen->GetWidth()) + { + snprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur); + drawText(right, y, CR_DARKGRAY, textbuf); + } + } + + + //============================================================================= + int Draw(FOptionMenuDescriptor *desc, int y, int indent, bool selected) override + { + drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor); + mDrawX = indent + CursorSpace(); + DrawSlider (mDrawX, y, mMin, mMax, GetSliderValue(), mShowValue, indent); + return indent; + } + + //============================================================================= + bool MenuEvent (int mkey, bool fromcontroller) override + { + double value = GetSliderValue(); + + if (mkey == MKEY_Left) + { + value -= mStep; + } + else if (mkey == MKEY_Right) + { + value += mStep; + } + else + { + return FOptionMenuItem::MenuEvent(mkey, fromcontroller); + } + SetSliderValue(clamp(value, mMin, mMax)); + M_MenuSound(ChangeSound); + return true; + } + + bool MouseEvent(int type, int x, int y) override + { + DOptionMenu *lm = static_cast(DMenu::CurrentMenu); + if (type != DMenu::MOUSE_Click) + { + if (!lm->CheckFocus(this)) return false; + } + if (type == DMenu::MOUSE_Release) + { + lm->ReleaseFocus(); + } + + int slide_left = mDrawX+8*CleanXfac_1; + int slide_right = slide_left + (10*8*CleanXfac_1 >> mSliderShort); // 10 char cells with 8 pixels each. + + if (type == DMenu::MOUSE_Click) + { + if (x < slide_left || x >= slide_right) return true; + } + + x = clamp(x, slide_left, slide_right); + double v = mMin + ((x - slide_left) * (mMax - mMin)) / (slide_right - slide_left); + if (v != GetSliderValue()) + { + SetSliderValue(v); + M_MenuSound(ChangeSound); + } + if (type == DMenu::MOUSE_Click) + { + lm->SetFocus(this); + } + return true; + } + +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuSliderCVar : public FOptionMenuSliderBase +{ + FBaseCVar *mCVar; +public: + FOptionMenuSliderCVar(const char *label, const char *menu, double min, double max, double step, int showval) + : FOptionMenuSliderBase(label, min, max, step, showval) + { + mCVar = FindCVar(menu, NULL); + } + + double GetSliderValue() override + { + if (mCVar != NULL) + { + return mCVar->GetGenericRep(CVAR_Float).Float; + } + else + { + return 0; + } + } + + void SetSliderValue(double val) override + { + if (mCVar != NULL) + { + UCVarValue value; + value.Float = (float)val; + mCVar->SetGenericRep(value, CVAR_Float); + } + } +}; + +//============================================================================= +// +// +// +//============================================================================= + +class FOptionMenuSliderVar : public FOptionMenuSliderBase +{ + float *mPVal; +public: + + FOptionMenuSliderVar(const char *label, float *pVal, double min, double max, double step, int showval) + : FOptionMenuSliderBase(label, min, max, step, showval) + { + mPVal = pVal; + } + + double GetSliderValue() override + { + return *mPVal; + } + + void SetSliderValue(double val) override + { + *mPVal = (float)val; + } +}; + + +//============================================================================= +// +// [TP] FOptionMenuFieldBase +// +// Base class for input fields +// +//============================================================================= + +class FOptionMenuFieldBase : public FOptionMenuItem +{ +public: + FOptionMenuFieldBase ( const char* label, const char* menu, const char* graycheck ) : + FOptionMenuItem ( label, menu ), + mCVar ( FindCVar( mAction, NULL )), + mGrayCheck (( graycheck && strlen( graycheck )) ? FindCVar( graycheck, NULL ) : NULL ) {} + + const char* GetCVarString() + { + if ( mCVar == NULL ) + return ""; + + return mCVar->GetGenericRep( CVAR_String ).String; + } + + virtual FString Represent() + { + return GetCVarString(); + } + + int Draw ( FOptionMenuDescriptor*, int y, int indent, bool selected ) override + { + bool grayed = mGrayCheck != NULL && !( mGrayCheck->GetGenericRep( CVAR_Bool ).Bool ); + drawLabel(indent, y, selected ? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, grayed); + drawValue(indent, y, OptionSettings.mFontColorValue, Represent(), grayed); + return indent; + } + + bool GetString ( int i, char* s, int len ) override + { + if ( i == 0 ) + { + strncpy( s, GetCVarString(), len ); + s[len - 1] = '\0'; + return true; + } + + return false; + } + + bool SetString ( int i, const char* s ) override + { + if ( i == 0 ) + { + if ( mCVar ) + { + UCVarValue vval; + vval.String = s; + mCVar->SetGenericRep( vval, CVAR_String ); + } + + return true; + } + + return false; + } + +protected: + // Action is a CVar in this class and derivatives. + FBaseCVar* mCVar; + FBaseCVar* mGrayCheck; +}; + +//============================================================================= +// +// [TP] FOptionMenuTextField +// +// A text input field widget, for use with string CVars. +// +//============================================================================= + +class FOptionMenuTextField : public FOptionMenuFieldBase +{ +public: + FOptionMenuTextField ( const char *label, const char* menu, const char* graycheck ) : + FOptionMenuFieldBase ( label, menu, graycheck ), + mEntering ( false ) {} + + FString Represent() override + { + FString text = mEntering ? mEditName : FString(GetCVarString()); + + if ( mEntering ) + text += '_'; + + return text; + } + + int Draw(FOptionMenuDescriptor*desc, int y, int indent, bool selected) override + { + if (mEntering) + { + // reposition the text so that the cursor is visible when in entering mode. + FString text = Represent(); + int tlen = NewSmallFont->StringWidth(text) * CleanXfac_1; + int newindent = screen->GetWidth() - tlen - CursorSpace(); + if (newindent < indent) indent = newindent; + } + return FOptionMenuFieldBase::Draw(desc, y, indent, selected); + } + + bool MenuEvent ( int mkey, bool fromcontroller ) override + { + if ( mkey == MKEY_Enter ) + { + M_MenuSound(AdvanceSound); + mEditName = GetCVarString(); + mEntering = true; + DMenu* input = new DTextEnterMenu(DMenu::CurrentMenu, NewSmallFont, mEditName, 256, fromcontroller ); + M_ActivateMenu( input ); + return true; + } + else if ( mkey == MKEY_Input ) + { + if ( mCVar ) + { + UCVarValue vval; + vval.String = mEditName; + mCVar->SetGenericRep( vval, CVAR_String ); + } + + mEntering = false; + return true; + } + else if ( mkey == MKEY_Abort ) + { + mEntering = false; + return true; + } + + return FOptionMenuItem::MenuEvent( mkey, fromcontroller ); + } + +private: + bool mEntering; + FString mEditName; +}; + +//============================================================================= +// +// [TP] FOptionMenuNumberField +// +// A numeric input field widget, for use with number CVars where sliders are inappropriate (i.e. +// where the user is interested in the exact value specifically) +// +//============================================================================= + +class FOptionMenuNumberField : public FOptionMenuFieldBase +{ +public: + FOptionMenuNumberField ( const char *label, const char* menu, float minimum, float maximum, + float step, const char* graycheck ) + : FOptionMenuFieldBase ( label, menu, graycheck ), + mMinimum ( minimum ), + mMaximum ( maximum ), + mStep ( step ) + { + if ( mMaximum <= mMinimum ) + std::swap( mMinimum, mMaximum ); + + if ( mStep <= 0 ) + mStep = 1; + } + + bool MenuEvent ( int mkey, bool fromcontroller ) override + { + if ( mCVar ) + { + float value = mCVar->GetGenericRep( CVAR_Float ).Float; + + if ( mkey == MKEY_Left ) + { + value -= mStep; + + if ( value < mMinimum ) + value = mMaximum; + } + else if ( mkey == MKEY_Right || mkey == MKEY_Enter ) + { + value += mStep; + + if ( value > mMaximum ) + value = mMinimum; + } + else + return FOptionMenuItem::MenuEvent( mkey, fromcontroller ); + + UCVarValue vval; + vval.Float = value; + mCVar->SetGenericRep( vval, CVAR_Float ); + M_MenuSound(ChangeSound); + } + + return true; + } + +private: + float mMinimum; + float mMaximum; + float mStep; +}; diff --git a/source/common/menu/savegamemanager.cpp b/source/common/menu/savegamemanager.cpp new file mode 100644 index 000000000..e6fa309d3 --- /dev/null +++ b/source/common/menu/savegamemanager.cpp @@ -0,0 +1,707 @@ +/* +** loadsavemenu.cpp +** The load game and save game menus +** +**--------------------------------------------------------------------------- +** Copyright 2001-2010 Randy Heit +** Copyright 2010 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "menu/menu.h" +#include "version.h" +#include "m_png.h" +#include "filesystem.h" +#include "v_text.h" +#include "d_event.h" +#include "gstrings.h" +#include "d_gui.h" +#include "v_draw.h" +#include "files.h" +#include "resourcefile.h" +#include "sjson.h" +#include "cmdlib.h" +#include "files.h" +#include "savegamehelp.h" +#include "i_specialpaths.h" +#include "c_dispatch.h" +#include "../../platform/win32/i_findfile.h" // This is a temporary direct path. Needs to be fixed when stuff gets cleaned up. + + +FSavegameManager savegameManager; + +void FSavegameManager::LoadGame(FSaveGameNode* node) +{ + if (gi->LoadGame(node)) + { + } +} + +void FSavegameManager::SaveGame(FSaveGameNode* node, bool ok4q, bool forceq) +{ + if (gi->SaveGame(node)) + { + FString fn = node->Filename; + FString desc = node->SaveTitle; + NotifyNewSave(fn, desc, ok4q, forceq); + } + +} + +//============================================================================= +// +// Save data maintenance +// +//============================================================================= + +void FSavegameManager::ClearSaveGames() +{ + for (unsigned i = 0; ibNoDelete) + delete SaveGames[i]; + } + SaveGames.Clear(); +} + +FSavegameManager::~FSavegameManager() +{ + ClearSaveGames(); +} + +//============================================================================= +// +// Save data maintenance +// +//============================================================================= + +int FSavegameManager::RemoveSaveSlot(int index) +{ + int listindex = SaveGames[0]->bNoDelete ? index - 1 : index; + if (listindex < 0) return index; + + remove(SaveGames[index]->Filename.GetChars()); + UnloadSaveData(); + + FSaveGameNode *file = SaveGames[index]; + + if (quickSaveSlot == SaveGames[index]) + { + quickSaveSlot = nullptr; + } + if (!file->bNoDelete) delete file; + + if (LastSaved == listindex) LastSaved = -1; + else if (LastSaved > listindex) LastSaved--; + if (LastAccessed == listindex) LastAccessed = -1; + else if (LastAccessed > listindex) LastAccessed--; + + SaveGames.Delete(index); + if ((unsigned)index >= SaveGames.Size()) index--; + ExtractSaveData(index); + return index; +} + +//============================================================================= +// +// +// +//============================================================================= + +int FSavegameManager::InsertSaveNode(FSaveGameNode *node) +{ + if (SaveGames.Size() == 0) + { + return SaveGames.Push(node); + } + + if (node->bOldVersion) + { // Add node at bottom of list + return SaveGames.Push(node); + } + else + { // Add node at top of list + unsigned int i; + for (i = 0; i < SaveGames.Size(); i++) + { + if (SaveGames[i]->bOldVersion || node->SaveTitle.CompareNoCase(SaveGames[i]->SaveTitle) <= 0) + { + break; + } + } + SaveGames.Insert(i, node); + return i; + } +} + +//============================================================================= +// +// M_ReadSaveStrings +// +// Find savegames and read their titles +// +//============================================================================= + +void FSavegameManager::ReadSaveStrings() +{ + if (SaveGames.Size() == 0) + { + void *filefirst; + findstate_t c_file; + FString filter; + + LastSaved = LastAccessed = -1; + quickSaveSlot = nullptr; + filter = G_BuildSaveName("*"); + filefirst = I_FindFirst(filter.GetChars(), &c_file); + if (filefirst != ((void *)(-1))) + { + do + { + // I_FindName only returns the file's name and not its full path + FString filepath = G_BuildSaveName(I_FindName(&c_file)); + + FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, true, true); + if (savegame != nullptr) + { + FResourceLump *info = savegame->FindLump("info.json"); + if (info == nullptr) + { + // savegame info not found. This is not a savegame so leave it alone. + delete savegame; + continue; + } + auto fr = info->NewReader(); + FString title; + int check = G_ValidateSavegame(fr, &title, true); + fr.Close(); + delete savegame; + if (check != 0) + { + FSaveGameNode *node = new FSaveGameNode; + node->Filename = filepath; + node->bOldVersion = check == -1; + node->bMissingWads = check == -2; + node->SaveTitle = title; + InsertSaveNode(node); + } + } + } while (I_FindNext (filefirst, &c_file) == 0); + I_FindClose (filefirst); + } + } +} + + +//============================================================================= +// +// +// +//============================================================================= + +void FSavegameManager::NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave) +{ + FSaveGameNode *node; + + if (file.IsEmpty()) + return; + + ReadSaveStrings(); + + // See if the file is already in our list + for (unsigned i = 0; iFilename.Compare(file) == 0) +#else + if (node->Filename.CompareNoCase(file) == 0) +#endif + { + node->SaveTitle = title; + node->bOldVersion = false; + node->bMissingWads = false; + if (okForQuicksave) + { + if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node; + LastAccessed = LastSaved = i; + } + return; + } + } + + node = new FSaveGameNode; + node->SaveTitle = title; + node->Filename = file; + node->bOldVersion = false; + node->bMissingWads = false; + int index = InsertSaveNode(node); + + if (okForQuicksave) + { + if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node; + LastAccessed = LastSaved = index; + } + else + { + LastAccessed = ++LastSaved; + } +} + +//============================================================================= +// +// Loads the savegame +// +//============================================================================= + +void FSavegameManager::LoadSavegame(int Selected) +{ + auto sel = savegameManager.GetSavegame(Selected); + if (sel && !sel->bOldVersion && !sel->bMissingWads) + { + savegameManager.LoadGame(SaveGames[Selected]); + if (quickSaveSlot == (FSaveGameNode*)1) + { + quickSaveSlot = SaveGames[Selected]; + } + M_ClearMenus(); + LastAccessed = Selected; + } +} + + +//============================================================================= +// +// +// +//============================================================================= + +void FSavegameManager::DoSave(int Selected, const char *savegamestring) +{ + if (Selected != 0) + { + auto node = *SaveGames[Selected]; + node.SaveTitle = savegamestring; + savegameManager.SaveGame(&node, true, false); + } + else + { + // Find an unused filename and save as that + FString filename; + int i; + + for (i = 0;; ++i) + { + filename = G_BuildSaveName(FStringf("save%04d", i)); + if (!FileExists(filename)) + { + break; + } + } + FSaveGameNode sg{ savegamestring, filename }; + savegameManager.SaveGame(&sg, true, false); + } + M_ClearMenus(); +} + + +//============================================================================= +// +// +// +//============================================================================= + +unsigned FSavegameManager::ExtractSaveData(int index) +{ + FResourceFile *resf; + FSaveGameNode *node; + + if (index == -1) + { + if (SaveGames.Size() > 0 && SaveGames[0]->bNoDelete) + { + index = LastSaved + 1; + } + else + { + index = LastAccessed < 0? 0 : LastAccessed; + } + } + + UnloadSaveData(); + + if ((unsigned)index < SaveGames.Size() && + (node = SaveGames[index]) && + !node->Filename.IsEmpty() && + !node->bOldVersion && + (resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr) + { + FResourceLump *info = resf->FindLump("info.json"); + if (info == nullptr) + { + // this should not happen because the file has already been verified. + return index; + } + auto fr = info->NewReader(); + auto data = fr.ReadPadded(1); + fr.Close(); + sjson_context* ctx = sjson_create_context(0, 0, NULL); + if (ctx) + { + sjson_node* root = sjson_decode(ctx, (const char*)data.Data()); + + + FString comment = sjson_get_string(root, "Creation Time", ""); + FString fcomment = sjson_get_string(root, "Map Label", ""); + FString ncomment = sjson_get_string(root, "Map Name", ""); + FStringf pcomment("%s - %s\n", fcomment.GetChars(), ncomment.GetChars()); + comment += pcomment; + SaveCommentString = comment; + + // Extract pic (todo: let the renderer write a proper PNG file instead of a raw canvas dunp of the software renderer - and make it work for all games.) + FResourceLump *pic = resf->FindLump("savepic.png"); + if (pic != nullptr) + { + FileReader picreader; + + picreader.OpenMemoryArray([=](TArray &array) + { + auto cache = pic->Lock(); + array.Resize(pic->LumpSize); + memcpy(&array[0], cache, pic->LumpSize); + pic->Unlock(); + return true; + }); + PNGHandle *png = M_VerifyPNG(picreader); + if (png != nullptr) + { + SavePic = nullptr; // not yet implemented: PNGTexture_CreateFromFile(png, node->Filename); + delete png; + if (SavePic && SavePic->GetWidth() == 1 && SavePic->GetHeight() == 1) + { + delete SavePic; + SavePic = nullptr; + SavePicData.Clear(); + } + } + } + } + delete resf; + } + return index; +} + +//============================================================================= +// +// +// +//============================================================================= + +void FSavegameManager::UnloadSaveData() +{ + if (SavePic != nullptr) + { + delete SavePic; + } + + SaveCommentString = ""; + SavePic = nullptr; + SavePicData.Clear(); +} + +//============================================================================= +// +// +// +//============================================================================= + +void FSavegameManager::ClearSaveStuff() +{ + UnloadSaveData(); + if (quickSaveSlot == (FSaveGameNode*)1) + { + quickSaveSlot = nullptr; + } +} + + +//============================================================================= +// +// +// +//============================================================================= + +bool FSavegameManager::DrawSavePic(int x, int y, int w, int h) +{ + if (SavePic == nullptr) return false; + DrawTexture(&twod, SavePic, x, y, DTA_DestWidth, w, DTA_DestHeight, h, DTA_Masked, false, TAG_DONE); + return true; +} + + +//============================================================================= +// +// +// +//============================================================================= + +void FSavegameManager::SetFileInfo(int Selected) +{ + if (!SaveGames[Selected]->Filename.IsEmpty()) + { + SaveCommentString.Format("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars()); + } +} + + +//============================================================================= +// +// +// +//============================================================================= + +unsigned FSavegameManager::SavegameCount() +{ + return SaveGames.Size(); +} + + +//============================================================================= +// +// +// +//============================================================================= + +FSaveGameNode *FSavegameManager::GetSavegame(int i) +{ + return SaveGames[i]; +} + + +//============================================================================= +// +// +// +//============================================================================= + +void FSavegameManager::InsertNewSaveNode() +{ + NewSaveNode.SaveTitle = GStrings("NEWSAVE"); + NewSaveNode.bNoDelete = true; + SaveGames.Insert(0, &NewSaveNode); +} + + +//============================================================================= +// +// +// +//============================================================================= + +bool FSavegameManager::RemoveNewSaveNode() +{ + if (SaveGames[0] == &NewSaveNode) + { + SaveGames.Delete(0); + return true; + } + return false; +} + +//============================================================================= +// +// +// +//============================================================================= + +CVAR(Bool, saveloadconfirmation, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) + +CVAR(Int, autosavenum, 0, CVAR_NOSET | CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +static int nextautosave = -1; +CVAR(Int, disableautosave, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, autosavecount, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 1) + self = 1; +} + +CVAR(Int, quicksavenum, 0, CVAR_NOSET | CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +static int nextquicksave = -1; + CUSTOM_CVAR(Int, quicksavecount, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 1) + self = 1; +} + +void M_Autosave() +{ + if (!gi->CanSave()) return; + FString description; + FString file; + // Keep a rotating sets of autosaves + UCVarValue num; + const char* readableTime; + int count = autosavecount != 0 ? autosavecount : 1; + + if (nextautosave == -1) + { + nextautosave = (autosavenum + 1) % count; + } + + num.Int = nextautosave; + autosavenum.ForceSet(num, CVAR_Int); + + FSaveGameNode sg; + sg.Filename = G_BuildSaveName(FStringf("auto%04d", nextautosave)); + readableTime = myasctime(); + sg.SaveTitle.Format("Autosave %s", readableTime); + nextautosave = (nextautosave + 1) % count; + savegameManager.SaveGame(&sg, false, false); +} + +CCMD(autosave) +{ + if (disableautosave) return; + M_Autosave(); +} + +CCMD(rotatingquicksave) +{ + if (!gi->CanSave()) return; + FString description; + FString file; + // Keep a rotating sets of quicksaves + UCVarValue num; + const char* readableTime; + int count = quicksavecount != 0 ? quicksavecount : 1; + + if (nextquicksave == -1) + { + nextquicksave = (quicksavenum + 1) % count; + } + + num.Int = nextquicksave; + quicksavenum.ForceSet(num, CVAR_Int); + + FSaveGameNode sg; + sg.Filename = G_BuildSaveName(FStringf("quick%04d", nextquicksave)); + readableTime = myasctime(); + sg.SaveTitle.Format("Quicksave %s", readableTime); + nextquicksave = (nextquicksave + 1) % count; + savegameManager.SaveGame(&sg, false, false); +} + + +//============================================================================= +// +// +// +//============================================================================= + +CCMD(quicksave) +{ // F6 + if (!gi->CanSave()) return; + + if (savegameManager.quickSaveSlot == NULL || savegameManager.quickSaveSlot == (FSaveGameNode*)1) + { + M_StartControlPanel(true); + M_SetMenu(NAME_SaveGameMenu); + return; + } + + auto slot = savegameManager.quickSaveSlot; + + // [mxd]. Just save the game, no questions asked. + if (!saveloadconfirmation) + { + savegameManager.SaveGame(savegameManager.quickSaveSlot, true, true); + return; + } + + gi->MenuSound(ActivateSound); + + FString tempstring = GStrings("QSPROMPT"); + tempstring.Substitute("%s", slot->SaveTitle.GetChars()); + + DMenu* newmenu = CreateMessageBoxMenu(DMenu::CurrentMenu, tempstring, 0, INT_MAX, false, NAME_None, [](bool res) + { + if (res) + { + savegameManager.SaveGame(savegameManager.quickSaveSlot, true, true); + } + }); + + M_ActivateMenu(newmenu); +} + +//============================================================================= +// +// +// +//============================================================================= + +CCMD(quickload) +{ // F9 +#if 0 + if (netgame) + { + M_StartControlPanel(true); + M_StartMessage(GStrings("QLOADNET"), 1); + return; + } +#endif + + if (savegameManager.quickSaveSlot == nullptr || savegameManager.quickSaveSlot == (FSaveGameNode*)1) + { + M_StartControlPanel(true); + // signal that whatever gets loaded should be the new quicksave + savegameManager.quickSaveSlot = (FSaveGameNode*)1; + M_SetMenu(NAME_LoadGameMenu); + return; + } + + // [mxd]. Just load the game, no questions asked. + if (!saveloadconfirmation) + { + savegameManager.LoadGame(savegameManager.quickSaveSlot); + return; + } + FString tempstring = GStrings("QLPROMPT"); + tempstring.Substitute("%s", savegameManager.quickSaveSlot->SaveTitle.GetChars()); + + M_StartControlPanel(true); + + DMenu* newmenu = CreateMessageBoxMenu(DMenu::CurrentMenu, tempstring, 0, INT_MAX, false, NAME_None, [](bool res) + { + if (res) + { + savegameManager.LoadGame(savegameManager.quickSaveSlot); + } + }); + M_ActivateMenu(newmenu); +} diff --git a/source/common/music/backend/i_sound.cpp b/source/common/music/backend/i_sound.cpp index 6cbda4a95..996e75bbe 100644 --- a/source/common/music/backend/i_sound.cpp +++ b/source/common/music/backend/i_sound.cpp @@ -53,6 +53,7 @@ #include "zmusic/zmusic.h" EXTERN_CVAR (Float, snd_sfxvolume) +EXTERN_CVAR(Float, mus_volume) CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Int, snd_hrtf, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) diff --git a/source/common/music/backend/oalsound.cpp b/source/common/music/backend/oalsound.cpp index ff8afc2f0..5506e445b 100644 --- a/source/common/music/backend/oalsound.cpp +++ b/source/common/music/backend/oalsound.cpp @@ -43,6 +43,7 @@ #include "cmdlib.h" #include "c_cvars.h" #include "printf.h" +#include "menu.h" #include "zmusic/sounddecoder.h" #include "filereadermusicinterface.h" @@ -96,7 +97,6 @@ bool IsOpenALPresent() -#if 0 void I_BuildALDeviceList(FOptionValues *opt) { opt->mValues.Resize(1); @@ -148,7 +148,6 @@ void I_BuildALResamplersList(FOptionValues *opt) } #endif } -#endif ReverbContainer *ForcedEnvironment; diff --git a/source/common/music/i_music.cpp b/source/common/music/i_music.cpp index 5cdd9b3c2..dd4093b1f 100644 --- a/source/common/music/i_music.cpp +++ b/source/common/music/i_music.cpp @@ -82,7 +82,8 @@ void I_InitMusicWin32(); // let the operating system decide for us. // //========================================================================== -EXTERN_CVAR(Bool, cd_enabled); +EXTERN_CVAR(Bool, cd_enabled); +EXTERN_CVAR(Float, snd_mastervolume) CUSTOM_CVAR(String, cd_drive, "", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) { @@ -115,17 +116,17 @@ CUSTOM_CVAR(Bool, cd_enabled, true, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBAL // Maximum volume of MOD/stream music. //========================================================================== -CUSTOM_CVARD(Int, mus_volume, 255, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls music volume") +CUSTOM_CVARD(Float, mus_volume, 0.5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls music volume") { if (self < 0) self = 0; - else if (self > 255) self = 255; + else if (self > 1) self = 1; else { // Set general music volume. - ChangeMusicSetting(ZMusic::snd_musicvolume, nullptr, self / 255.f); + ChangeMusicSetting(ZMusic::snd_musicvolume, nullptr, self); if (GSnd != nullptr) { - GSnd->SetMusicVolume(clamp(self / 255.f * relative_volume/* * snd_mastervolume*/, 0, 1)); + GSnd->SetMusicVolume(clamp(self * relative_volume * snd_mastervolume, 0, 1)); } // For music not implemented through the digital sound system, // let them know about the change. @@ -140,6 +141,12 @@ CUSTOM_CVARD(Int, mus_volume, 255, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls mus } } +CUSTOM_CVARD(Bool, mus_enabled, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enables/disables music") +{ + if (self) S_RestartMusic(); + else S_StopMusic(true); +} + //========================================================================== // // Callbacks for the music system. @@ -219,7 +226,7 @@ static void SetupGenMidi() { // The OPL renderer should not care about where this comes from. // Note: No I_Error here - this needs to be consistent with the rest of the music code. - auto lump = fileSystem.FindFile("demolition/genmidi.dat"); + auto lump = fileSystem.FindFile("demolition/genmidi.op2"); if (lump < 0) { Printf("No GENMIDI lump found. OPL playback not available."); diff --git a/source/common/music/music.cpp b/source/common/music/music.cpp index d521ff13e..340b03124 100644 --- a/source/common/music/music.cpp +++ b/source/common/music/music.cpp @@ -1,29 +1,11 @@ -//----------------------------------------------------------------------------- -// -// Copyright 1993-1996 id Software -// Copyright 1999-2016 Randy Heit -// Copyright 2002-2016 Christoph Oelckers -// -// 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 -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//----------------------------------------------------------------------------- -// -// DESCRIPTION: none -// -//----------------------------------------------------------------------------- - -/* For code that originates from ZDoom the following applies: +/* +** +** music.cpp +** +** music engine - borrowed from GZDoom +** +** Copyright 1999-2016 Randy Heit +** Copyright 2002-2016 Christoph Oelckers ** **--------------------------------------------------------------------------- ** @@ -68,6 +50,8 @@ #include "c_dispatch.h" #include "gamecontrol.h" #include "filereadermusicinterface.h" +#include "savegamehelp.h" +#include "sjson.h" MusPlayingInfo mus_playing; MusicAliasMap MusicAliases; @@ -75,6 +59,10 @@ MidiDeviceMap MidiDevices; MusicVolumeMap MusicVolumes; MusicAliasMap LevelMusicAliases; bool MusicPaused; +static bool mus_blocked; +static FString lastStartedMusic; +EXTERN_CVAR(Float, mus_volume) + //========================================================================== // // @@ -190,6 +178,7 @@ void S_ResumeMusic () void S_UpdateMusic () { + mus_blocked = false; if (mus_playing.handle != nullptr) { ZMusic_Update(mus_playing.handle); @@ -251,6 +240,7 @@ bool S_StartMusic (const char *m_id) bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) { + lastStartedMusic = musicname; // remember the last piece of music that was requested to be played. if (musicname == nullptr || musicname[0] == 0) { // Don't choke if the map doesn't have a song attached @@ -263,16 +253,6 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) FString DEH_Music; - FName* aliasp = MusicAliases.CheckKey(musicname); - if (aliasp != nullptr) - { - if (*aliasp == NAME_None) - { - return true; // flagged to be ignored - } - musicname = aliasp->GetChars(); - } - if (!mus_playing.name.IsEmpty() && mus_playing.handle != nullptr && stricmp(mus_playing.name, musicname) == 0 && @@ -360,8 +340,8 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) // shutdown old music S_StopMusic (true); - // Just record it if volume is 0 - if (mus_volume <= 0) + // Just record it if volume is 0 or music was disabled + if (mus_volume <= 0 || !mus_enabled) { mus_playing.loop = looping; mus_playing.name = musicname; @@ -416,12 +396,11 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force) // // S_RestartMusic // -// Must only be called from snd_reset in i_sound.cpp! //========================================================================== void S_RestartMusic () { - if (!mus_playing.LastSong.IsEmpty()) + if (!mus_playing.LastSong.IsEmpty() && mus_volume > 0 && mus_enabled) { FString song = mus_playing.LastSong; mus_playing.LastSong = ""; @@ -557,6 +536,7 @@ CCMD (stopmus) static FString lastMusicLevel, lastMusic; int Mus_Play(const char *mapname, const char *fn, bool loop) { + if (mus_blocked) return 0; // Store the requested names for resuming. lastMusicLevel = mapname; lastMusic = fn; @@ -565,16 +545,11 @@ int Mus_Play(const char *mapname, const char *fn, bool loop) { return 0; } - // A restart was requested. Ignore the music name being passed and just try tp restart what got here last. - if (mapname && *mapname == '*') - { - mapname = lastMusicLevel.GetChars(); - fn = lastMusic.GetChars(); - } + // Allow per level music substitution. - // Unlike some other engines like ZDoom or even Blood which use definition files, the music names in Duke Nukem are being defined in a CON script, making direct replacement a lot harder. // For most cases using $musicalias would be sufficient, but that method only works if a level actually has some music defined at all. - // This way it can be done with an add-on definition lump even in cases like Redneck Rampage where no music definitions exist or where music gets reused for multiple levels but replacement is wanted individually. + // This way it can be done with an add-on definition lump even in cases like Redneck Rampage where no music definitions exist + // or where music gets reused for multiple levels but replacement is wanted individually. if (mapname && *mapname) { if (*mapname == '/') mapname++; @@ -582,18 +557,104 @@ int Mus_Play(const char *mapname, const char *fn, bool loop) if (check) fn = check->GetChars(); } + // Now perform music aliasing. This also needs to be done before checking identities because multiple names can map to the same song. + FName* aliasp = MusicAliases.CheckKey(fn); + if (aliasp != nullptr) + { + if (*aliasp == NAME_None) + { + return true; // flagged to be ignored + } + fn = aliasp->GetChars(); + } + + if (!mus_restartonload) + { + // If the currently playing piece of music is the same, do not restart. Note that there's still edge cases where this may fail to detect identities. + if (mus_playing.handle != nullptr && lastStartedMusic.CompareNoCase(fn) == 0 && mus_playing.loop) + return true; + } + S_ChangeMusic(fn, 0, loop, true); return mus_playing.handle != nullptr; } void Mus_Stop() { + if (mus_blocked) return; S_StopMusic(true); } +void Mus_Fade(double seconds) +{ + // Todo: Blood uses this, but the streamer cannot currently fade the volume. + Mus_Stop(); +} + void Mus_SetPaused(bool on) { if (on) S_PauseMusic(); else S_ResumeMusic(); } +void MUS_Save() +{ + FString music = mus_playing.name; + if (music.IsEmpty()) music = mus_playing.LastSong; + + sjson_context* ctx = sjson_create_context(0, 0, NULL); + if (!ctx) + { + return; + } + sjson_node* root = sjson_mkobject(ctx); + sjson_put_string(ctx, root, "music", music); + sjson_put_int(ctx, root, "baseorder", mus_playing.baseorder); + sjson_put_bool(ctx, root, "loop", mus_playing.loop); + + char* encoded = sjson_stringify(ctx, root, " "); + + FileWriter* fil = WriteSavegameChunk("music.json"); + if (!fil) + { + sjson_destroy_context(ctx); + return; + } + + fil->Write(encoded, strlen(encoded)); + + sjson_free_string(ctx, encoded); + sjson_destroy_context(ctx); +} + +bool MUS_Restore() +{ + auto fil = ReadSavegameChunk("music.json"); + if (!fil.isOpen()) + { + return false; + } + + auto text = fil.ReadPadded(1); + fil.Close(); + + if (text.Size() == 0) + { + return false; + } + + sjson_context* ctx = sjson_create_context(0, 0, NULL); + sjson_node* root = sjson_decode(ctx, (const char*)text.Data()); + mus_playing.LastSong = sjson_get_string(root, "music", ""); + mus_playing.baseorder = sjson_get_int(root, "baseorder", 0); + mus_playing.loop = sjson_get_bool(root, "loop", true); + sjson_destroy_context(ctx); + mus_blocked = true; // this is to prevent scripts from resetting the music after it has been loaded from the savegame. + + return true; +} + +void MUS_ResumeSaved() +{ + S_RestartMusic(); +} diff --git a/source/common/music/music_config.cpp b/source/common/music/music_config.cpp index e28875606..2f8cc98ab 100644 --- a/source/common/music/music_config.cpp +++ b/source/common/music/music_config.cpp @@ -74,7 +74,7 @@ CUSTOM_CVAR(String, fluid_lib, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTU FORWARD_STRING_CVAR(fluid_lib); } -CUSTOM_CVAR(String, fluid_patchset, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, fluid_patchset, "demolition", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(fluid_patchset); } @@ -273,7 +273,7 @@ CUSTOM_CVAR(Float, min_sustain_time, 5000, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CV FORWARD_CVAR(min_sustain_time); } -CUSTOM_CVAR(String, timidity_config, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, timidity_config, "demolition", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(timidity_config); } diff --git a/source/common/music/music_midi_base.cpp b/source/common/music/music_midi_base.cpp index 02bf631f9..6c1b615f1 100644 --- a/source/common/music/music_midi_base.cpp +++ b/source/common/music/music_midi_base.cpp @@ -33,32 +33,150 @@ #define DEF_MIDIDEV -5 -static uint32_t nummididevices; -#define NUM_DEF_DEVICES 7 +#define NUM_DEF_DEVICES 3 #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include - -void I_InitMusicWin32 () -{ - nummididevices = midiOutGetNumDevs (); -} - - #endif #include "c_dispatch.h" #include "v_text.h" +#include "menu/menu.h" #include "zmusic/zmusic.h" #include "s_music.h" #include "c_cvars.h" #include "printf.h" EXTERN_CVAR(Int, snd_mididevice) +static uint32_t nummididevices; + + +static void AddDefaultMidiDevices(FOptionValues *opt) +{ + FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(NUM_DEF_DEVICES)]; + pair[0].Text = "FluidSynth"; + pair[0].Value = -5.0; + pair[1].Text = "TiMidity++"; + pair[1].Value = -2.0; + pair[2].Text = "OPL Synth Emulation"; + pair[2].Value = -3.0; + +} + +#ifdef _WIN32 + +void I_InitMusicWin32 () +{ + nummididevices = midiOutGetNumDevs (); +} + +void I_BuildMIDIMenuList (FOptionValues *opt) +{ + AddDefaultMidiDevices(opt); + + for (uint32_t id = 0; id < nummididevices; ++id) + { + MIDIOUTCAPS caps; + MMRESULT res; + + res = midiOutGetDevCaps (id, &caps, sizeof(caps)); + assert(res == MMSYSERR_NOERROR); + if (res == MMSYSERR_NOERROR) + { + FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(1)]; + pair->Text = caps.szPname; + pair->Value = (float)id; + } + } +} + +static void PrintMidiDevice (int id, const char *name, uint16_t tech, uint32_t support) +{ + if (id == snd_mididevice) + { + Printf (TEXTCOLOR_BOLD); + } + Printf ("% 2d. %s : ", id, name); + switch (tech) + { + case MIDIDEV_MIDIPORT: Printf ("MIDIPORT"); break; + case MIDIDEV_SYNTH: Printf ("SYNTH"); break; + case MIDIDEV_SQSYNTH: Printf ("SQSYNTH"); break; + case MIDIDEV_FMSYNTH: Printf ("FMSYNTH"); break; + case MIDIDEV_MAPPER: Printf ("MAPPER"); break; + case MIDIDEV_WAVETABLE: Printf ("WAVETABLE"); break; + case MIDIDEV_SWSYNTH: Printf ("SWSYNTH"); break; + } + if (support & MIDICAPS_CACHE) + { + Printf (" CACHE"); + } + if (support & MIDICAPS_LRVOLUME) + { + Printf (" LRVOLUME"); + } + if (support & MIDICAPS_STREAM) + { + Printf (" STREAM"); + } + if (support & MIDICAPS_VOLUME) + { + Printf (" VOLUME"); + } + Printf (TEXTCOLOR_NORMAL "\n"); +} + +CCMD (snd_listmididevices) +{ + UINT id; + MIDIOUTCAPS caps; + MMRESULT res; + + PrintMidiDevice(-8, "libOPN", MIDIDEV_FMSYNTH, 0); + PrintMidiDevice(-7, "libADL", MIDIDEV_FMSYNTH, 0); + PrintMidiDevice (-6, "WildMidi", MIDIDEV_SWSYNTH, 0); + PrintMidiDevice (-5, "FluidSynth", MIDIDEV_SWSYNTH, 0); + PrintMidiDevice (-4, "Gravis Ultrasound Emulation", MIDIDEV_SWSYNTH, 0); + PrintMidiDevice (-3, "Emulated OPL FM Synth", MIDIDEV_FMSYNTH, 0); + PrintMidiDevice (-2, "TiMidity++", MIDIDEV_SWSYNTH, 0); + if (nummididevices != 0) + { + for (id = 0; id < nummididevices; ++id) + { + FString text; + res = midiOutGetDevCaps (id, &caps, sizeof(caps)); + if (res == MMSYSERR_NODRIVER) + text = ""; + else if (res == MMSYSERR_NOMEM) + text = ""; + else if (res == MMSYSERR_NOERROR) + text = caps.szPname; + else + continue; + + PrintMidiDevice (id, text, caps.wTechnology, caps.dwSupport); + } + } +} + +#else + +void I_BuildMIDIMenuList (FOptionValues *opt) +{ + AddDefaultMidiDevices(opt); +} + +CCMD (snd_listmididevices) +{ + Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : ""); + Printf("%s-3. Emulated OPL FM Synth\n", -3 == snd_mididevice ? TEXTCOLOR_BOLD : ""); + Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : ""); +} +#endif CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) diff --git a/source/common/music/s_music.h b/source/common/music/s_music.h index bca472f67..96f9eb16a 100644 --- a/source/common/music/s_music.h +++ b/source/common/music/s_music.h @@ -97,5 +97,11 @@ extern MusPlayingInfo mus_playing; extern float relative_volume, saved_relative_volume; +void MUS_Save(); +bool MUS_Restore(); + +// Note for later when the OPL player is ported. +// DN3D and related games use "d3dtimbr.tmb" + #endif diff --git a/source/common/music/z_music.h b/source/common/music/z_music.h index 754aca1dd..e2dff877a 100644 --- a/source/common/music/z_music.h +++ b/source/common/music/z_music.h @@ -5,4 +5,6 @@ void Mus_Init(); int Mus_Play(const char *mapname, const char *fn, bool loop); void Mus_Stop(); +void Mus_Fade(double seconds); void Mus_SetPaused(bool on); +void MUS_ResumeSaved(); diff --git a/source/common/openaudio.cpp b/source/common/openaudio.cpp index f57869096..423a17525 100644 --- a/source/common/openaudio.cpp +++ b/source/common/openaudio.cpp @@ -13,7 +13,7 @@ static FileReader S_TryFormats(char * const testfn, char * const fn_suffix, char #ifdef HAVE_FLAC { Bstrcpy(fn_suffix, ".flac"); - auto fp = kopenFileReader(testfn, searchfirst); + auto fp = fileSystem.OpenFileReader(testfn, searchfirst); if (fp.isOpen()) return fp; } @@ -22,7 +22,7 @@ static FileReader S_TryFormats(char * const testfn, char * const fn_suffix, char #ifdef HAVE_VORBIS { Bstrcpy(fn_suffix, ".ogg"); - auto fp = kopenFileReader(testfn, searchfirst); + auto fp = fileSystem.OpenFileReader(testfn, searchfirst); if (fp.isOpen()) return fp; } @@ -64,7 +64,7 @@ static FileReader S_TryExtensionReplacements(char * const testfn, char const sea FileReader S_OpenAudio(const char *fn, char searchfirst, uint8_t const ismusic) { - auto origfp = kopenFileReader(fn, searchfirst); + auto origfp = fileSystem.OpenFileReader(fn, searchfirst); if (!snd_tryformats) return origfp; return origfp; #if 0 // this needs to be redone diff --git a/source/common/openaudio.h b/source/common/openaudio.h index e9fee2288..ac3a6c2de 100644 --- a/source/common/openaudio.h +++ b/source/common/openaudio.h @@ -1,4 +1,6 @@ #pragma once +#include "filesystem/filesystem.h" + // This really, really needs to be redone in its entirety, the audio lookup code is hideous. extern FileReader S_OpenAudio(const char *fn, char searchfirst, uint8_t ismusic); diff --git a/source/common/optionmenu/optionmenu.cpp b/source/common/optionmenu/optionmenu.cpp deleted file mode 100644 index 78ee8adb2..000000000 --- a/source/common/optionmenu/optionmenu.cpp +++ /dev/null @@ -1,96 +0,0 @@ - - - -#include "imgui.h" -#include "v_draw.h" -#include "gamecvars.h" -#include "c_buttons.h" -#include "c_bind.h" -#include "inputstate.h" - -FString activeCommand; - -void sendKeyForBinding(int key) -{ - Bindings.DoBind(KeyName(key), activeCommand); - GUICapture &= ~8; -} - - -bool ShowOptionMenu() -{ - bool isOpen = true; - int w = screen->GetWidth(), h = screen->GetHeight(); - double scale; - if (w >= 1024 && h >= 768) - { - scale = 1; - ImGui::SetNextWindowPos(ImVec2((w-1024)/2, (h-768)/2), ImGuiCond_Always); - ImGui::SetNextWindowSize(ImVec2(1024, 768), ImGuiCond_Always); - } - else - { - // This should use a smaller font! - scale = 640.0/1024.0; - ImGui::SetNextWindowPos(ImVec2((w-640)/2, (h-480)/2), ImGuiCond_Always); - ImGui::SetNextWindowSize(ImVec2(640, 480), ImGuiCond_Always); - } - - - const int window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - // Main body of the Demo window starts here. - if (!ImGui::Begin("Customize Controls", &isOpen, window_flags)) - { - // Early out if the window is collapsed, as an optimization. - ImGui::End(); - return false; - } - FString emptiness = " "; - - for (int i = 0; i < NUMGAMEFUNCTIONS; i++) - { - FString al = buttonMap.GetButtonAlias(i); - FString cmd = "+" + al; - if (al.IsNotEmpty()) - { - al.Substitute('_', ' '); - ImGui::Text(al.GetChars()); - ImGui::SameLine(300*scale); - al = buttonMap.GetButtonName(i); - auto binds = Bindings.GetKeysForCommand(cmd); - al = C_NameKeys(binds.Data(), binds.Size()); - // This looks like an ImGui bug - it doesn't like two identically labelled buttons on the same page, it seems. - // Work around this by using strings with different numbers of spaces. Stupid but effective. - if (al.IsEmpty()) { al = emptiness; emptiness << " "; } - if (ImGui::Button(al, ImVec2(450 * scale, 0))) - { - activeCommand = cmd; - ImGui::OpenPopup("Bind"); - } - } - } - if (ImGui::BeginPopupModal("Bind", NULL, ImGuiWindowFlags_AlwaysAutoResize)) - { - auto binds = Bindings.GetKeysForCommand(activeCommand); - auto al = C_NameKeys(binds.Data(), binds.Size()); - - ImGui::Text("Press 'bind' to enter binding mode or\n'delete' to clear all bindings for this action\n\nCurrently bound to this action:\n%s\n\n", al.GetChars()); - ImGui::Separator(); - if (ImGui::Button("Done", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); } - ImGui::SetItemDefaultFocus(); - ImGui::SameLine(); - if (ImGui::Button("Clear", ImVec2(120, 0))) { Bindings.UnbindACommand(activeCommand); } - ImGui::SameLine(); - if (ImGui::Button("Bind", ImVec2(120, 0))) - { - // Todo: Set event handler to binding mode. - // Wait for a bound key to arrive and add to the current command. - GUICapture |= 8; - } - ImGui::EndPopup(); - } - - - ImGui::End(); - return isOpen; -} \ No newline at end of file diff --git a/source/common/quotemgr.h b/source/common/quotemgr.h new file mode 100644 index 000000000..3de93401e --- /dev/null +++ b/source/common/quotemgr.h @@ -0,0 +1,65 @@ +#pragma once + +#include "zstring.h" +#include "gstrings.h" +// Reimplementation of the Duke quote string buffer. +// Needed because these strings need a level of abstraction from the engine to allow localization +// and because some of the quotes are really status messages that need to be shared between the different games. +// Also a good opportunity to consolidate the data buffers from Duke and Redneck frontends. + +enum +{ + MAXQUOTES = 16384, +}; + +class Quotes +{ + FString quotes[MAXQUOTES]; + FString exquotes[MAXQUOTES]; + + void MakeStringLabel(FString "e); + +public: + + void InitializeQuote(int num, const char *text, bool fromscript = false); + void InitializeExQuote(int num, const char *text, bool fromscript = false); + + const char *GetQuote(int num) + { + return GStrings.localize(quotes[num]); + } + + const char *GetExQuote(int num) + { + return GStrings.localize(exquotes[num]); + } + + const char *GetRawQuote(int num) + { + return quotes[num]; + } + + const char *GetRawExQuote(int num) + { + return exquotes[num]; + } + + void CopyQuote(int dst, int src) + { + quotes[dst] = quotes[src]; + } + + void CopyExQuote(int dst, int src) + { + quotes[dst] = exquotes[src]; + } + + void AppendQuote(int dst, int src, int len = -1); + void AppendExQuote(int dst, int src, int len = -1); + void FormatQuote(int dst, const char* fmt, ...); + void Substitute(int num, const char* text, const char* replc); + void ReadFromSavegame(); + void WriteToSavegame(); +}; + +extern Quotes quoteMgr; diff --git a/source/common/quotes.cpp b/source/common/quotes.cpp new file mode 100644 index 000000000..1b2099d1a --- /dev/null +++ b/source/common/quotes.cpp @@ -0,0 +1,182 @@ +/* +** +** quotes.cpp +** Duke-Nukem-style quote buffer +** +**--------------------------------------------------------------------------- +** Copyright 2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** This is actually a VERY inefficient way to manage strings +** but needs to be preserved because the CON VM depends on it. +*/ + +#include "quotemgr.h" +#include "savegamehelp.h" +#include "sjson.h" + + +void Quotes::MakeStringLabel(FString "e) +{ + // Only prepend a quote if the string is localizable. + if (quote.Len() > 0 && quote[0] != '$' && GStrings[quote]) quote.Insert(0, "$"); +} + +void Quotes::InitializeQuote(int num, const char *text, bool fromscript) +{ + quotes[num] = text; + if (fromscript) // means this is the initial setup from the source data. + { + MakeStringLabel(quotes[num]); + } +} + +void Quotes::InitializeExQuote(int num, const char *text, bool fromscript) +{ + exquotes[num] = text; + if (fromscript) // means this is the initial setup from the source data. + { + MakeStringLabel(quotes[num]); + } +} + +void Quotes::AppendQuote(int dst, int src, int len) +{ + // This needs to apply the localization because the combined string is not localizable anymore. + if (quotes[dst][0] == '$') quotes[dst] = GStrings.localize(quotes[dst]); + if (len < 0) quotes[dst] << GStrings.localize(quotes[src]); + else quotes[dst] += FString(GStrings.localize(quotes[src]), len); +} + +void Quotes::AppendExQuote(int dst, int src, int len) +{ + // This needs to apply the localization because the combined string is not localizable anymore. + if (quotes[dst][0] == '$') quotes[dst] = GStrings.localize(quotes[dst]); + if (len < 0) quotes[dst] << GStrings.localize(exquotes[src]); + else quotes[dst] += FString(GStrings.localize(exquotes[src]), len); +} + + +void Quotes::FormatQuote(int dst, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + quotes[dst].VFormat(fmt, ap); +} + +void Quotes::Substitute(int dst, const char* text, const char* replc) +{ + if (quotes[dst][0] == '$') quotes[dst] = GStrings.localize(quotes[dst]); + quotes[dst].Substitute(text, replc); +} + + +void Quotes::ReadFromSavegame() +{ + for (auto& q : quotes) q = ""; + for (auto& q : exquotes) q = ""; + + auto fil = ReadSavegameChunk("quotes.json"); + if (!fil.isOpen()) + { + return; + } + + auto text = fil.ReadPadded(1); + fil.Close(); + + if (text.Size() == 0) + { + return; + } + + sjson_context* ctx = sjson_create_context(0, 0, NULL); + sjson_node* root = sjson_decode(ctx, (const char*)text.Data()); + + auto qs = sjson_find_member(root, "quotes"); + auto xs = sjson_find_member(root, "exquotes"); + + sjson_node* q; + sjson_foreach(q, qs) + { + int index = (int)strtoll(q->key, nullptr, 10); + quotes[index] = q->string_; + } + sjson_foreach(q, xs) + { + int index = (int)strtoll(q->key, nullptr, 10); + exquotes[index] = q->string_; + } + sjson_destroy_context(ctx); +} + +void Quotes::WriteToSavegame() +{ + sjson_context* ctx = sjson_create_context(0, 0, NULL); + if (!ctx) + { + return; + } + sjson_node* root = sjson_mkobject(ctx); + sjson_node* qs = sjson_mkobject(ctx); + sjson_node* xs = sjson_mkobject(ctx); + + for (unsigned i = 0; i < MAXQUOTES; i++) + { + if (quotes[i].IsNotEmpty()) + { + char buff[10]; + snprintf(buff, 10, "%d", i); + sjson_append_member(ctx, qs, buff, sjson_mkstring(ctx, quotes[i])); + } + if (exquotes[i].IsNotEmpty()) + { + char buff[10]; + snprintf(buff, 10, "%d", i); + sjson_append_member(ctx, xs, buff, sjson_mkstring(ctx, exquotes[i])); + } + } + sjson_append_member(ctx, root, "quotes", qs); + sjson_append_member(ctx, root, "exquotes", xs); + + char* encoded = sjson_stringify(ctx, root, " "); + FileWriter* fil = WriteSavegameChunk("quotes.json"); + if (!fil) + { + sjson_destroy_context(ctx); + return; + } + + fil->Write(encoded, strlen(encoded)); + + sjson_free_string(ctx, encoded); + sjson_destroy_context(ctx); + return; + +} + +Quotes quoteMgr; diff --git a/source/common/rts.cpp b/source/common/rts.cpp index f0cb6a9f1..372d12805 100644 --- a/source/common/rts.cpp +++ b/source/common/rts.cpp @@ -35,7 +35,7 @@ #include #include "zstring.h" #include "tarray.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" #include "rts.h" #include "m_swap.h" @@ -80,7 +80,7 @@ bool RTS_IsInitialized() { if (LumpInfo.Size() > 0) return true; if (RTSName.IsEmpty()) return false; - auto fr = kopenFileReader(RTSName, 0); + auto fr = fileSystem.OpenFileReader(RTSName, 0); RTSName = ""; // don't try ever again. if (!fr.isOpen()) return false; RTSFile = fr.Read(); diff --git a/source/common/savegamehelp.cpp b/source/common/savegamehelp.cpp index 3a3cdffa7..29d6e7025 100644 --- a/source/common/savegamehelp.cpp +++ b/source/common/savegamehelp.cpp @@ -1,5 +1,7 @@ /* ** savegame.cpp +** +** common savegame utilities for all front ends. ** **--------------------------------------------------------------------------- ** Copyright 2019 Christoph Oelckers @@ -29,21 +31,39 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **--------------------------------------------------------------------------- ** -** This is for keeping my sanity while working with the horrible mess -** that is the savegame code in Duke Nukem. -** Without handling this in global variables it is a losing proposition -** to save custom data along with the regular snapshot. :( -** With this the savegame code can mostly pretend to load from and write -** to files while really using a composite archive. -*/ +*/ #include "compositesaveame.h" #include "savegamehelp.h" - +#include "sjson.h" +#include "baselayer.h" +#include "gstrings.h" +#include "i_specialpaths.h" +#include "cmdlib.h" +#include "filesystem/filesystem.h" +#include "statistics.h" +#include "secrets.h" +#include "s_music.h" +#include "quotemgr.h" +#include "mapinfo.h" static CompositeSavegameWriter savewriter; static FResourceFile *savereader; +//============================================================================= +// +// This is for keeping my sanity while working with the horrible mess +// that is the savegame code in Duke Nukem. +// Without handling this in global variables it is a losing proposition +// to save custom data along with the regular snapshot. :( +// With this the savegame code can mostly pretend to load from and write +// to files while really using a composite archive. +// +// All global non-game dependent state is also saved right here for convenience. +// +//============================================================================= + + void OpenSaveGameForWrite(const char *name) { savewriter.Clear(); @@ -54,6 +74,29 @@ bool OpenSaveGameForRead(const char *name) { if (savereader) delete savereader; savereader = FResourceFile::OpenResourceFile(name, true, true); + + if (savereader != nullptr) + { + // Load system-side data from savegames. + ReadStatistics(); + SECRET_Load(); + MUS_Restore(); + quoteMgr.ReadFromSavegame(); + + auto file = ReadSavegameChunk("info.json"); + if (!file.isOpen()) + { + FinishSavegameRead(); + delete savereader; + return false; + } + if (G_ValidateSavegame(file, nullptr, false) <= 0) + { + FinishSavegameRead(); + delete savereader; + return false; + } + } return savereader != nullptr; } @@ -80,3 +123,220 @@ void FinishSavegameRead() delete savereader; savereader = nullptr; } + +//============================================================================= +// +// Writes the header which is used to display the savegame in the menu. +// +//============================================================================= + +void G_WriteSaveHeader(const char *name) +{ + sjson_context* ctx = sjson_create_context(0, 0, NULL); + if (!ctx) + { + return; + } + sjson_node* root = sjson_mkobject(ctx); + auto savesig = gi->GetSaveSig(); + sjson_put_int(ctx, root, "Save Version", savesig.currentsavever); + sjson_put_string(ctx, root, "Engine", savesig.savesig); + sjson_put_string(ctx, root, "Game Resource", fileSystem.GetResourceFileName(1)); + sjson_put_string(ctx, root, "Map Name", currentLevel->DisplayName()); + sjson_put_string(ctx, root, "Title", name); + sjson_put_string(ctx, root, "Map File", currentLevel->fileName); + sjson_put_string(ctx, root, "Map Label", currentLevel->labelName); + const char *fn = currentLevel->fileName; + if (*fn == '/') fn++; + if (strncmp(fn, "file://", 7) != 0) // this only has meaning for non-usermaps + { + auto fileno = fileSystem.FindFile(fn); + auto mapfile = fileSystem.GetFileContainer(fileno); + auto mapcname = fileSystem.GetResourceFileName(mapfile); + if (mapcname) sjson_put_string(ctx, root, "Map Resource", mapcname); + else return; // this should never happen. Saving on a map that isn't present is impossible. + } + + char* encoded = sjson_stringify(ctx, root, " "); + + FileWriter* fil = WriteSavegameChunk("info.json"); + if (!fil) + { + sjson_destroy_context(ctx); + return; + } + + fil->Write(encoded, strlen(encoded)); + + sjson_free_string(ctx, encoded); + sjson_destroy_context(ctx); + + // Handle system-side modules that need to persist data in savegames here, in a central place. + SaveStatistics(); + SECRET_Save(); + MUS_Save(); + quoteMgr.WriteToSavegame(); +} + +//============================================================================= +// +// +// +//============================================================================= + +static bool CheckSingleFile (const char *name, bool &printRequires, bool printwarn) +{ + if (name == NULL) + { + return true; + } + if (strncmp(name, "file://", 7) == 0) + { + return FileExists(name + 7); // User maps must be present to be validated. + } + if (fileSystem.CheckIfResourceFileLoaded(name) < 0) + { + if (printwarn) + { + if (!printRequires) + { + Printf ("%s:\n%s", GStrings("TXT_SAVEGAMENEEDS"), name); + } + else + { + Printf (", %s", name); + } + } + printRequires = true; + return false; + } + return true; +} + +//============================================================================= +// +// Return false if not all the needed wads have been loaded. +// +//============================================================================= + +static bool G_CheckSaveGameWads (const char *gamegrp, const char *mapgrp, bool printwarn) +{ + bool printRequires = false; + CheckSingleFile (gamegrp, printRequires, printwarn); + CheckSingleFile (mapgrp, printRequires, printwarn); + + if (printRequires) + { + if (printwarn) + { + Printf ("\n"); + } + return false; + } + + return true; +} + +//============================================================================= +// +// Checks if the savegame is valid. Gets a reader to the included info.json +// Returns 1 if valid, 0 if invalid and -1 if old and -2 if content missing +// +//============================================================================= + +int G_ValidateSavegame(FileReader &fr, FString *savetitle, bool formenu) +{ + auto data = fr.ReadPadded(1); + + sjson_context* ctx = sjson_create_context(0, 0, NULL); + if (ctx) + { + sjson_node* root = sjson_decode(ctx, (const char*)data.Data()); + + + int savever = sjson_get_int(root, "Save Version", -1); + FString engine = sjson_get_string(root, "Engine", ""); + FString gamegrp = sjson_get_string(root, "Game Resource", ""); + FString mapgrp = sjson_get_string(root, "Map Resource", ""); + FString title = sjson_get_string(root, "Title", ""); + FString filename = sjson_get_string(root, "Map File", ""); + auto savesig = gi->GetSaveSig(); + + sjson_destroy_context(ctx); + + if (savetitle) *savetitle = title; + if (engine.Compare(savesig.savesig) != 0 || savever > savesig.currentsavever) + { + // different engine or newer version: + // not our business. Leave it alone. + return 0; + } + + MapRecord *curLevel = nullptr; + + if (strncmp(filename, "file://", 7) != 0) + { + for (auto& mr : mapList) + { + if (mr.fileName.Compare(filename) == 0) + { + curLevel = &mr; + } + } + } + else + { + curLevel = &userMapRecord; + if (!formenu) + { + userMapRecord.name = ""; + userMapRecord.SetFileName(filename); + } + } + if (!curLevel) return 0; + if (!formenu) currentLevel = curLevel; + + + if (savever < savesig.minsavever) + { + // old, incompatible savegame. List as not usable. + return -1; + } + else + { + auto ggfn = ExtractFileBase(fileSystem.GetResourceFileName(1), true); + if (gamegrp.CompareNoCase(ggfn) == 0) + { + return G_CheckSaveGameWads(gamegrp, mapgrp, false) ? 1 : -2; + } + else + { + // different game. Skip this. + return 0; + } + } + } + return 0; +} + +//============================================================================= +// +// +// +//============================================================================= + +FString G_BuildSaveName (const char *prefix) +{ + FString name = M_GetSavegamesPath(); + size_t len = name.Len(); + if (name[0] != '\0' && name[len-1] != '\\' && name[len-1] != '/') + { + name << "/"; + } + name << prefix; + if (!strchr(prefix, '.')) name << SAVEGAME_EXT; // only add an extension if the prefix doesn't have one already. + name = NicePath(name); + name.Substitute("\\", "/"); + return name; +} + diff --git a/source/common/savegamehelp.h b/source/common/savegamehelp.h index 9dec6d617..a7e0f839d 100644 --- a/source/common/savegamehelp.h +++ b/source/common/savegamehelp.h @@ -10,3 +10,13 @@ FileReader ReadSavegameChunk(const char *name); bool FinishSavegameWrite(); void FinishSavegameRead(); + +// Savegame utilities +class FileReader; + +FString G_BuildSaveName (const char *prefix); +int G_ValidateSavegame(FileReader &fr, FString *savetitle, bool formenu); +void G_WriteSaveHeader(const char* name); + +#define SAVEGAME_EXT ".dsave" + diff --git a/source/common/searchpaths.cpp b/source/common/searchpaths.cpp index a617f9bc8..6e1aeb8bd 100644 --- a/source/common/searchpaths.cpp +++ b/source/common/searchpaths.cpp @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gamecontrol.h" #include "filesystem/filesystem.h" +static const char* res_exts[] = { ".grp", ".zip", ".pk3", ".pk4", ".7z", ".pk7" }; namespace fs = std::filesystem; @@ -161,7 +162,7 @@ static void AddAnItem(const char* item) void G_AddExternalSearchPaths(TArray &searchpaths) { FString path; - char *homepath = Bgethomedir(); + char *homepath = getenv("HOME"); path.Format("%s/.steam/steam", homepath); G_AddSteamPaths(searchpaths, buf); @@ -811,7 +812,7 @@ static TArray ParseGrpInfo(const char *fn, FileReader &fr, TMap GrpScan() TArray sortedFileList; TArray sortedGroupList; + TArray contentGroupList; auto allFiles = CollectAllFilesInSearchPath(); auto allGroups = ParseAllGrpInfos(allFiles); @@ -937,8 +939,58 @@ TArray GrpScan() // Remove all unnecessary content from the file list. Since this contains all data from the search path's directories it can be quite large. // Sort both lists by file size so that we only need to pass over each list once to weed out all unrelated content. Go backward to avoid too much item movement // (most will be deleted anyway.) + + for (auto& f : allFiles) sortedFileList.Push(&f); - for (auto& g : allGroups) sortedGroupList.Push(&g); + for (auto& g : allGroups) + { + if (g.CRC == 0 && g.mustcontain.Size() > 0) + contentGroupList.Push(&g); + else + sortedGroupList.Push(&g); + } + + // As a first pass we need to look for all known game resources which only are identified by a content list + if (contentGroupList.Size()) + { + for (auto fe : sortedFileList) + { + FString fn = fe->FileName.MakeLower(); + for (auto ext : res_exts) + { + if (strcmp(ext, fn.GetChars() + fn.Len() - 4) == 0) + { + auto resf = FResourceFile::OpenResourceFile(fe->FileName, true, true); + if (resf) + { + for (auto grp : contentGroupList) + { + bool ok = true; + for (auto &lump : grp->mustcontain) + { + if (!resf->FindLump(lump)) + { + ok = false; + break; + } + } + if (ok) + { + // got a match + foundGames.Reserve(1); + auto& fg = foundGames.Last(); + fg.FileInfo = *grp; + fg.FileName = fe->FileName; + fg.FileIndex = fe->Index; + break; + } + } + } + } + } + } + } + std::sort(sortedFileList.begin(), sortedFileList.end(), [](FileEntry* lhs, FileEntry* rhs) { return lhs->FileLength < rhs->FileLength; }); std::sort(sortedGroupList.begin(), sortedGroupList.end(), [](GrpInfo* lhs, GrpInfo* rhs) { return lhs->size < rhs->size; }); @@ -946,6 +998,7 @@ TArray GrpScan() int findex = sortedFileList.Size() - 1; int gindex = sortedGroupList.Size() - 1; + while (findex > 0 && gindex > 0) { if (sortedFileList[findex]->FileLength > sortedGroupList[gindex]->size) @@ -1018,9 +1071,9 @@ TArray GrpScan() for (unsigned i = 0; i < foundGames.Size(); i++) { - for (unsigned j = foundGames.Size(); j > i; j--) + for (unsigned j = foundGames.Size() - 1; j > i; j--) { - if (foundGames[i].FileInfo.CRC == foundGames[j].FileInfo.CRC) + if (foundGames[i].FileInfo.CRC == foundGames[j].FileInfo.CRC && foundGames[j].FileInfo.CRC != 0) foundGames.Delete(j); } } @@ -1099,7 +1152,7 @@ const char* G_DefaultConFile(void) } if (g_gameType & GAMEFLAG_SW) - return nullptr; // SW has no scripts of any kind (todo: Make Blood's INI files usable here for map definitions) + return nullptr; // SW has no scripts of any kind. if (g_gameType & GAMEFLAG_NAM) { diff --git a/source/common/secrets.cpp b/source/common/secrets.cpp index 21cd0d5d7..d06700ca0 100644 --- a/source/common/secrets.cpp +++ b/source/common/secrets.cpp @@ -1,5 +1,5 @@ #include "c_dispatch.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" #include "printf.h" #include "v_text.h" #include "tarray.h" @@ -166,7 +166,7 @@ void SECRET_SetMapName(const char *filename, const char *_maptitle) void SECRET_Trigger(int num) { - if (secret_notify) Printf(PRINT_NONOTIFY, "Secret #%d found\n", num); + if (secret_notify) Printf("Secret #%d found\n", num); if (discovered_secrets.Find(num) == discovered_secrets.Size()) discovered_secrets.Push(num); } diff --git a/source/common/statistics.cpp b/source/common/statistics.cpp index 868ff3e5c..8405e541c 100644 --- a/source/common/statistics.cpp +++ b/source/common/statistics.cpp @@ -47,6 +47,7 @@ #include "baselayer.h" #include "savegamehelp.h" #include "sjson.h" +#include "gstrings.h" CVAR(Int, savestatistics, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(String, statfile, "demolitionstat.txt", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -259,7 +260,8 @@ static void SaveStatistics(const char *fn, TArray &statlist) { fw->Printf("\t{\n"); - qsort(&ls[0], ls.Size(), sizeof(ls[0]), compare_level_names); + // Only makes sense if level names follow a strict format. This is noz the case here. + //qsort(&ls[0], ls.Size(), sizeof(ls[0]), compare_level_names); for(unsigned k=0;k= ArtFiles.Size()) // Do not process if already loaded. { - FileReader fr = kopenFileReader(fn, 0); + FileReader fr = fileSystem.OpenFileReader(fn, 0); if (fr.isOpen()) { auto artdata = fr.Read(); @@ -339,6 +340,10 @@ void BuildTiles::LoadArtSet(const char* filename) FStringf fn(filename, index); LoadArtFile(fn, false); } + for (auto& addart : addedArt) + { + LoadArtFile(addart, false); + } } @@ -557,16 +562,19 @@ void artClearMapArt(void) //========================================================================== // -// Load map specfici ART +// Load map specficied ART // //========================================================================== +static FString currentMapArt; void artSetupMapArt(const char* filename) { + if (currentMapArt.CompareNoCase(filename)) return; + currentMapArt = filename; artClearMapArt(); FStringf firstname("%s_00.art", filename); - auto fr = kopenFileReader(firstname, 0); + auto fr = fileSystem.OpenFileReader(firstname, 0); if (!fr.isOpen()) return; for (bssize_t i = 0; i < MAXARTFILES_TOTAL - MAXARTFILES_BASE; i++) diff --git a/source/common/textures/formats/arttexture.cpp b/source/common/textures/formats/arttexture.cpp index 2f0d75ab7..b5c1157fd 100644 --- a/source/common/textures/formats/arttexture.cpp +++ b/source/common/textures/formats/arttexture.cpp @@ -118,7 +118,7 @@ FArtTexture::FArtTexture(int width, int height, int p) void FArtTexture::CreatePalettedPixels(uint8_t* buffer) { - FileReader fr = kopenFileReader(Name, 0); + FileReader fr = fileSystem.OpenFileReader(Name, 0); if (!fr.isOpen()) return; int numpixels = Width * Height; fr.Read(buffer, numpixels); @@ -139,7 +139,7 @@ int FArtTexture::CopyPixels(FBitmap *bmp, int conversion) // Both Src and Dst are ordered the same with no padding. int numpixels = Width * Height; bool hasalpha = false; - FileReader fr = kopenFileReader(Name, 0); + FileReader fr = fileSystem.OpenFileReader(Name, 0); if (!fr.isOpen()) return 0; TArray source(numpixels, true); fr.Read(source.Data(), numpixels); diff --git a/source/common/textures/formats/ddstexture.cpp b/source/common/textures/formats/ddstexture.cpp index f8160ba94..7527c4359 100644 --- a/source/common/textures/formats/ddstexture.cpp +++ b/source/common/textures/formats/ddstexture.cpp @@ -55,7 +55,7 @@ #include "imagehelpers.h" #include "image.h" #include "m_png.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" // Since we want this to compile under Linux too, we need to define this // stuff ourselves instead of including a DirectX header. @@ -374,7 +374,7 @@ void FDDSTexture::CalcBitShift (uint32_t mask, uint8_t *lshiftp, uint8_t *rshift void FDDSTexture::CreatePalettedPixels(uint8_t *buffer) { - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return; // Just leave the texture blank. lump.Seek (sizeof(DDSURFACEDESC2) + 4, FileReader::SeekSet); @@ -781,7 +781,7 @@ void FDDSTexture::DecompressDXT5 (FileReader &lump, bool premultiplied, uint8_t int FDDSTexture::CopyPixels(FBitmap *bmp, int conversion) { - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return -1; // Just leave the texture blank. uint8_t *TexBuffer = bmp->GetPixels(); diff --git a/source/common/textures/formats/jpegtexture.cpp b/source/common/textures/formats/jpegtexture.cpp index 19404fd79..5f3b0e2ad 100644 --- a/source/common/textures/formats/jpegtexture.cpp +++ b/source/common/textures/formats/jpegtexture.cpp @@ -40,7 +40,7 @@ #include "printf.h" #include "bitmap.h" #include "image.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" #include "imagehelpers.h" #include "v_text.h" @@ -262,7 +262,7 @@ FJPEGTexture::FJPEGTexture (int width, int height) void FJPEGTexture::CreatePalettedPixels(uint8_t *buffer) { - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return; // Just leave the texture blank. JSAMPLE *buff = NULL; @@ -385,7 +385,7 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion) { PalEntry pe[256]; - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return -1; // Just leave the texture blank. jpeg_decompress_struct cinfo; diff --git a/source/common/textures/formats/pcxtexture.cpp b/source/common/textures/formats/pcxtexture.cpp index 807c1560f..9a0c3d348 100644 --- a/source/common/textures/formats/pcxtexture.cpp +++ b/source/common/textures/formats/pcxtexture.cpp @@ -39,7 +39,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" //========================================================================== // @@ -350,7 +350,7 @@ void FPCXTexture::CreatePalettedPixels(uint8_t *buffer) PCXHeader header; int bitcount; - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return; // Just leave the texture blank. lump.Read(&header, sizeof(header)); @@ -436,7 +436,7 @@ int FPCXTexture::CopyPixels(FBitmap *bmp, int conversion) int bitcount; TArray Pixels; - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return -1; // Just leave the texture blank. lump.Read(&header, sizeof(header)); diff --git a/source/common/textures/formats/pngtexture.cpp b/source/common/textures/formats/pngtexture.cpp index 21660c8d9..1ed4dcf5d 100644 --- a/source/common/textures/formats/pngtexture.cpp +++ b/source/common/textures/formats/pngtexture.cpp @@ -41,7 +41,7 @@ #include "imagehelpers.h" #include "image.h" #include "printf.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" //========================================================================== // @@ -291,7 +291,7 @@ void FPNGTexture::CreatePalettedPixels(uint8_t *buffer) FileReader *lump; FileReader lfr; - lfr = kopenFileReader(Name, 0); + lfr = fileSystem.OpenFileReader(Name, 0); if (!lfr.isOpen()) return; lump = 𝔩 @@ -408,7 +408,7 @@ int FPNGTexture::CopyPixels(FBitmap *bmp, int conversion) FileReader *lump; FileReader lfr; - lfr = kopenFileReader(Name, 0); + lfr = fileSystem.OpenFileReader(Name, 0); if (!lfr.isOpen()) return -1; // Just leave the texture blank. lump = 𝔩 diff --git a/source/common/textures/formats/stbtexture.cpp b/source/common/textures/formats/stbtexture.cpp index e0dd82f63..d9bf916f2 100644 --- a/source/common/textures/formats/stbtexture.cpp +++ b/source/common/textures/formats/stbtexture.cpp @@ -49,7 +49,7 @@ #include "bitmap.h" #include "imagehelpers.h" #include "image.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" //========================================================================== // @@ -154,7 +154,7 @@ void FStbTexture::CreatePalettedPixels(uint8_t *buffer) int FStbTexture::CopyPixels(FBitmap *bmp, int conversion) { - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return -1; // Just leave the texture blank. int x, y, chan; auto image = stbi_load_from_callbacks(&callbacks, &lump, &x, &y, &chan, STBI_rgb_alpha); diff --git a/source/common/textures/formats/tgatexture.cpp b/source/common/textures/formats/tgatexture.cpp index 6a8596e72..d920160e7 100644 --- a/source/common/textures/formats/tgatexture.cpp +++ b/source/common/textures/formats/tgatexture.cpp @@ -37,7 +37,7 @@ #include "templates.h" #include "bitmap.h" #include "image.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" #include "imagehelpers.h" @@ -179,7 +179,7 @@ void FTGATexture::ReadCompressed(FileReader &lump, uint8_t * buffer, int bytespe void FTGATexture::CreatePalettedPixels(uint8_t *buffer) { uint8_t PaletteMap[256]; - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return; TGAHeader hdr; uint16_t w; @@ -385,7 +385,7 @@ void FTGATexture::CreatePalettedPixels(uint8_t *buffer) int FTGATexture::CopyPixels(FBitmap *bmp, int conversion) { PalEntry pe[256]; - auto lump = kopenFileReader(Name, 0); + auto lump = fileSystem.OpenFileReader(Name, 0); if (!lump.isOpen()) return -1; TGAHeader hdr; uint16_t w; diff --git a/source/common/textures/image.cpp b/source/common/textures/image.cpp index 5fd7759e7..39ee8018d 100644 --- a/source/common/textures/image.cpp +++ b/source/common/textures/image.cpp @@ -38,7 +38,7 @@ #include "bitmap.h" #include "image.h" #include "files.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" #include "imagehelpers.h" int FImageSource::NextID; @@ -79,7 +79,7 @@ FImageSource * FImageSource::GetImage(const char *name) { nullptr } }; - auto data = kopenFileReader(name, 0); + auto data = fileSystem.OpenFileReader(name, 0); if (!data.isOpen()) return nullptr; for (size_t i = 0; CreateInfo[i].TryCreate; i++) diff --git a/source/common/textures/textures.h b/source/common/textures/textures.h index a96d2b8c0..469ebaeed 100644 --- a/source/common/textures/textures.h +++ b/source/common/textures/textures.h @@ -506,6 +506,7 @@ struct BuildTiles FTexture* tiles[MAXTILES]; FTexture* tilesbak[MAXTILES]; TMap textures; + TArray addedArt; BuildTiles() { @@ -537,6 +538,10 @@ struct BuildTiles int LoadArtFile(const char* file, bool mapart = false, int firsttile = -1); void CloseAllMapArt(); void LoadArtSet(const char* filename); + void AddArt(TArray& art) + { + addedArt = std::move(art); + } FTexture* ValidateCustomTile(int tilenum, int type); int32_t artLoadFiles(const char* filename); uint8_t* tileMakeWritable(int num); diff --git a/source/common/utility/cmdlib.cpp b/source/common/utility/cmdlib.cpp index 90ceba980..dcae2ec8d 100644 --- a/source/common/utility/cmdlib.cpp +++ b/source/common/utility/cmdlib.cpp @@ -47,6 +47,7 @@ #endif #endif #include "cmdlib.h" +#include "compat.h" #include #include @@ -391,6 +392,33 @@ void CreatePath(const char *fn) } #endif +//========================================================================== +// +// myasctime +// +// [RH] Returns the current local time as ASCII, even if it's too early +// +//========================================================================== + +const char* myasctime() +{ + static char readabletime[50]; + time_t clock; + struct tm* lt; + + time(&clock); + lt = localtime(&clock); + if (lt != NULL) + { + strftime(readabletime, 50, "%F %T", lt); + return readabletime; + } + else + { + return "Unknown Time"; + } +} + //========================================================================== // // strbin -- In-place version @@ -730,3 +758,17 @@ bool IsAbsPath(const char *name) #endif /* _WIN32 */ return 0; } + +//========================================================================== +// +// +// +//========================================================================== + +void NormalizeFileName(FString &str) +{ + auto strp = str.LockBuffer(); + Bcorrectfilename(strp, false); + str.UnlockBuffer(); +} + diff --git a/source/common/utility/cmdlib.h b/source/common/utility/cmdlib.h index eec968e1f..cda5b8a74 100644 --- a/source/common/utility/cmdlib.h +++ b/source/common/utility/cmdlib.h @@ -27,6 +27,7 @@ bool DirEntryExists (const char *pathname, bool *isdir = nullptr); extern FString progdir; void DefaultExtension (FString &path, const char *extension); +void NormalizeFileName(FString &str); FString ExtractFilePath (const char *path); FString ExtractFileBase (const char *path, bool keep_extension=false); @@ -36,6 +37,7 @@ bool IsNum (const char *str); // [RH] added bool CheckWildcards (const char *pattern, const char *text); +const char* myasctime(); int strbin (char *str); FString strbin1 (const char *start); diff --git a/source/zmusic/i_music.h b/source/common/utility/gstrings.h similarity index 84% rename from source/zmusic/i_music.h rename to source/common/utility/gstrings.h index af45ec1fe..b9b8fff62 100644 --- a/source/zmusic/i_music.h +++ b/source/common/utility/gstrings.h @@ -1,5 +1,5 @@ /* -** i_music.h +** gstrings.h ** **--------------------------------------------------------------------------- ** Copyright 1998-2006 Randy Heit @@ -31,23 +31,18 @@ ** */ -#ifndef __I_MUSIC_H__ -#define __I_MUSIC_H__ +#ifndef __GSTRINGS_H__ +#define __GSTRINGS_H__ -class FileReader; -struct FOptionValues; +#ifdef _MSC_VER +#pragma once +#endif -// -// MUSIC I/O -// -void I_InitMusic (); -void I_BuildMIDIMenuList (FOptionValues *); +#include "stringtable.h" -// Volume. -void I_SetRelativeVolume(float); -void I_SetMusicVolume (double volume); +extern FStringTable GStrings; + +extern const char *endmsg[]; -extern int nomusic; - -#endif //__I_MUSIC_H__ +#endif //__GSTRINGS_H__ diff --git a/source/common/utility/m_argv.h b/source/common/utility/m_argv.h index 2e822dee7..8684b1fd1 100644 --- a/source/common/utility/m_argv.h +++ b/source/common/utility/m_argv.h @@ -50,28 +50,28 @@ public: iterator begin() { - return &Argv[0]; + return Argv.begin(); } const_iterator begin() const { - return &Argv[0]; + return Argv.begin(); } const_iterator cbegin() const { - return &Argv[0]; + return Argv.begin(); } iterator end() { - return &Argv[Argv.Size()]; + return Argv.end(); } const_iterator end() const { - return &Argv[Argv.Size()]; + return Argv.end(); } const_iterator cend() const { - return &Argv[Argv.Size()]; + return Argv.end(); } FArgs(); diff --git a/source/common/utility/name.h b/source/common/utility/name.h index 76324fe7c..1d7f2a581 100644 --- a/source/common/utility/name.h +++ b/source/common/utility/name.h @@ -34,6 +34,8 @@ #ifndef NAME_H #define NAME_H +#include "tarray.h" + enum ENamedName { #define xx(n) NAME_##n, @@ -50,8 +52,6 @@ public: FName (const char *text) { Index = NameData.FindName (text, false); } FName (const char *text, bool noCreate) { Index = NameData.FindName (text, noCreate); } FName (const char *text, size_t textlen, bool noCreate) { Index = NameData.FindName (text, textlen, noCreate); } - FName (const FString &text); - FName (const FString &text, bool noCreate); FName (const FName &other) = default; FName (ENamedName index) { Index = index; } // ~FName () {} // Names can be added but never removed. @@ -122,4 +122,13 @@ protected: static NameManager NameData; }; + +template<> struct THashTraits +{ + hash_t Hash(FName key) + { + return key.GetIndex(); + } + int Compare(FName left, FName right) { return left != right; } +}; #endif diff --git a/source/common/utility/namedef.h b/source/common/utility/namedef.h index d0cfff7b7..3fdb641b3 100644 --- a/source/common/utility/namedef.h +++ b/source/common/utility/namedef.h @@ -1,4 +1,10 @@ // 'None' must always be the first name. + +// Windows.h is just dangerous! +#ifdef LoadMenu +#undef LoadMenu +#endif + xx(None) xx(Null) xx(_) @@ -8,3 +14,33 @@ xx(SEQ) xx(SFX) xx(RAW) xx(MAP) +xx(Controlmessage) + +xx(MainMenu) +xx(IngameMenu) +xx(MultiMenu) +xx(HelpMenu) +xx(CreditsMenu) +xx(SaveGameMenu) +xx(LoadGameMenu) +xx(SoundMenu) +xx(ConfirmPlayerReset) +xx(EpisodeMenu) +xx(SkillMenu) +xx(CustomGameMenu) +xx(CustomSubMenu1) +xx(CustomSubMenu2) +xx(CustomSubMenu3) +xx(CustomSubMenu4) +xx(CustomSubMenu5) +xx(CustomSubMenu6) +xx(CustomSubMenu7) +xx(UsermapMenu) +xx(StartGame) +xx(ImageScroller) +xx(QuitMenu) +xx(EndgameMenu) +xx(Mididevices) +xx(Aldevices) +xx(Alresamplers) +xx(AdvSoundOptions) \ No newline at end of file diff --git a/source/common/utility/printf.h b/source/common/utility/printf.h index 3eef5e088..e8c706f57 100644 --- a/source/common/utility/printf.h +++ b/source/common/utility/printf.h @@ -23,7 +23,7 @@ enum PRINT_LOG, // only to logfile PRINT_BOLD = 200, // What Printf_Bold used PRINT_TYPES = 1023, // Bitmask. - PRINT_NONOTIFY = 1024, // Flag - do not add to notify buffer + PRINT_NOTIFY = 1024, // Flag - add to notify buffer PRINT_NOLOG = 2048, // Flag - do not print to log file }; @@ -39,6 +39,9 @@ enum void I_Error(const char *fmt, ...) ATTRIBUTE((format(printf,1,2))); +// This really could need some cleanup - the main problem is that it'd create +// lots of potential for merge conflicts. + int PrintString (int iprintlevel, const char *outline); int VPrintf(int printlevel, const char* format, va_list parms); int Printf (int printlevel, const char *format, ...) ATTRIBUTE((format(printf,2,3))); @@ -49,18 +52,20 @@ int DPrintf (int level, const char *format, ...) ATTRIBUTE((format(printf,2,3))) void OSD_Printf(const char *format, ...) ATTRIBUTE((format(printf,1,2))); template -inline void initprintf(const char *format, Args&&... args) ATTRIBUTE((format(printf,1,2))) +inline void initprintf(const char *format, Args&&... args) //ATTRIBUTE((format(printf,1,2))) { OSD_Printf(format, std::forward(args)...); } // This was a define before - which should be avoided. Used by Shadow Warrior template -inline void buildprintf(const char *format, Args&&... args) ATTRIBUTE((format(printf,1,2))) +inline void buildprintf(const char *format, Args&&... args) //ATTRIBUTE((format(printf,1,2))) { OSD_Printf(format, std::forward(args)...); } + + inline void initputs(const char *s) { PrintString(PRINT_HIGH, s); diff --git a/source/common/utility/sc_man.cpp b/source/common/utility/sc_man.cpp index 0f09f1a36..6cd7ff42a 100644 --- a/source/common/utility/sc_man.cpp +++ b/source/common/utility/sc_man.cpp @@ -20,7 +20,8 @@ #include "printf.h" #include "name.h" #include "v_text.h" -#include "cache1d.h" +#include "templates.h" +#include "filesystem/filesystem.h" // MACROS ------------------------------------------------------------------ @@ -143,7 +144,7 @@ FScanner &FScanner::operator=(const FScanner &other) void FScanner::Open (const char *name) { - auto fr = kopenFileReader(name, 0); + auto fr = fileSystem.OpenFileReader(name, 0); if (!fr.isOpen()) { I_Error("Could not find script lump '%s'\n", name); @@ -544,13 +545,13 @@ bool FScanner::GetToken () { TokenType = TK_UIntConst; BigNumber = (int64_t)strtoull(String, &stopper, 0); - Number = (int)clamp(BigNumber, 0, UINT_MAX); + Number = (int)clamp(BigNumber, 0, UINT_MAX); Float = (unsigned)Number; } else { BigNumber = strtoll(String, &stopper, 0); - Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); + Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); Float = Number; } } @@ -652,7 +653,7 @@ bool FScanner::GetNumber () else { BigNumber = strtoll(String, &stopper, 0); - Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); + Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); if (*stopper != 0) { ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", String); @@ -709,7 +710,7 @@ bool FScanner::CheckNumber () else { BigNumber = strtoll (String, &stopper, 0); - Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); + Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); if (*stopper != 0) { UnGet(); diff --git a/source/common/utility/stringtable.cpp b/source/common/utility/stringtable.cpp new file mode 100644 index 000000000..5f5b9809f --- /dev/null +++ b/source/common/utility/stringtable.cpp @@ -0,0 +1,678 @@ +/* +** stringtable.cpp +** Implements the FStringTable class +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include + +#include "stringtable.h" +#include "cmdlib.h" +#include "filesystem.h" +#include "sc_man.h" +#include "c_dispatch.h" +#include "v_text.h" +#include "c_cvars.h" +#include "printf.h" + +bool validFilter(const char *str); +EXTERN_CVAR(String, language) +CUSTOM_CVAR(Int, cl_gender, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0 || self > 3) self = 0; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FStringTable::LoadStrings () +{ + int lastlump, lump; + + lastlump = 0; + while ((lump = fileSystem.Iterate("demolition/lmacros", &lastlump, ELookupMode::NoExtension)) != -1) + { + readMacros(lump); + } + + lastlump = 0; + while ((lump = fileSystem.Iterate ("demolition/language", &lastlump, ELookupMode::NoExtension)) != -1) + { + auto lumpdata = fileSystem.GetFileData(lump); + + if (!ParseLanguageCSV(lump, lumpdata)) + LoadLanguage (lump, lumpdata); + } + UpdateLanguage(); + allMacros.Clear(); +} + + +//========================================================================== +// +// This was tailored to parse CSV as exported by Google Docs. +// +//========================================================================== + + +TArray> FStringTable::parseCSV(const TArray &buffer) +{ + const size_t bufLength = buffer.Size(); + TArray> data; + TArray row; + TArray cell; + bool quoted = false; + + /* + auto myisspace = [](int ch) { return ch == '\t' || ch == '\r' || ch == '\n' || ch == ' '; }; + while (*vcopy && myisspace((unsigned char)*vcopy)) vcopy++; // skip over leaading whitespace; + auto vend = vcopy + strlen(vcopy); + while (vend > vcopy && myisspace((unsigned char)vend[-1])) *--vend = 0; // skip over trailing whitespace + */ + + for (size_t i = 0; i < bufLength; ++i) + { + if (buffer[i] == '"') + { + // Double quotes inside a quoted string count as an escaped quotation mark. + if (quoted && i < bufLength - 1 && buffer[i + 1] == '"') + { + cell.Push('"'); + i++; + } + else if (cell.Size() == 0 || quoted) + { + quoted = !quoted; + } + } + else if (buffer[i] == ',') + { + if (!quoted) + { + cell.Push(0); + ProcessEscapes(cell.Data()); + row.Push(cell.Data()); + cell.Clear(); + } + else + { + cell.Push(buffer[i]); + } + } + else if (buffer[i] == '\r') + { + // Ignore all CR's. + } + else if (buffer[i] == '\n' && !quoted) + { + cell.Push(0); + ProcessEscapes(cell.Data()); + row.Push(cell.Data()); + data.Push(std::move(row)); + cell.Clear(); + } + else + { + cell.Push(buffer[i]); + } + } + + // Handle last line without linebreak + if (cell.Size() > 0 || row.Size() > 0) + { + cell.Push(0); + ProcessEscapes(cell.Data()); + row.Push(cell.Data()); + data.Push(std::move(row)); + } + return data; +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FStringTable::readMacros(int lumpnum) +{ + auto lumpdata = fileSystem.GetFileData(lumpnum); + auto data = parseCSV(lumpdata); + + for (unsigned i = 1; i < data.Size(); i++) + { + auto macroname = data[i][0]; + auto language = data[i][1]; + if (macroname.IsEmpty() || language.IsEmpty()) continue; + FStringf combined_name("%s/%s", language.GetChars(), macroname.GetChars()); + FName name = combined_name.GetChars(); + + StringMacro macro; + + for (int k = 0; k < 4; k++) + { + macro.Replacements[k] = data[i][k+2]; + } + allMacros.Insert(name, macro); + } + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray &buffer) +{ + if (memcmp(buffer.Data(), "default,", 8)) return false; + auto data = parseCSV(buffer); + + int labelcol = -1; + int filtercol = -1; + TArray> langrows; + bool hasDefaultEntry = false; + + if (data.Size() > 0) + { + for (unsigned column = 0; column < data[0].Size(); column++) + { + auto &entry = data[0][column]; + if (entry.CompareNoCase("filter") == 0) + { + filtercol = column; + } + else if (entry.CompareNoCase("identifier") == 0) + { + labelcol = column; + } + else + { + auto languages = entry.Split(" ", FString::TOK_SKIPEMPTY); + for (auto &lang : languages) + { + if (lang.CompareNoCase("default") == 0) + { + langrows.Push(std::make_pair(column, default_table)); + hasDefaultEntry = true; + } + else if (lang.Len() < 4) + { + lang.ToLower(); + langrows.Push(std::make_pair(column, MAKE_ID(lang[0], lang[1], lang[2], 0))); + } + } + } + } + + for (unsigned i = 1; i < data.Size(); i++) + { + auto &row = data[i]; +#if 1 + if (filtercol > -1) + { + auto filterstr = row[filtercol]; + if (filterstr.IsNotEmpty()) + { + auto filter = filterstr.Split(" ", FString::TOK_SKIPEMPTY); + bool ok = false; + for (auto& entry : filter) + { + if (validFilter(entry)) + { + ok = true; + break; + } + } + if (!ok) continue; + } + } +#endif + + FName strName = row[labelcol].GetChars(); + if (hasDefaultEntry) + { + DeleteForLabel(lumpnum, strName); + } + for (auto &langentry : langrows) + { + auto str = row[langentry.first]; + if (str.Len() > 0) + { + InsertString(lumpnum, langentry.second, strName, str); + } + else + { + DeleteString(langentry.second, strName); + } + } + } + } + return true; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FStringTable::LoadLanguage (int lumpnum, const TArray &buffer) +{ + bool errordone = false; + TArray activeMaps; + FScanner sc; + bool hasDefaultEntry = false; + + sc.OpenMem("LANGUAGE", (const char*)buffer.Data(), buffer.Size()); + sc.SetCMode (true); + while (sc.GetString ()) + { + if (sc.Compare ("[")) + { // Process language identifiers + activeMaps.Clear(); + sc.MustGetString (); + do + { + size_t len = sc.StringLen; + if (len != 2 && len != 3) + { + if (len == 1 && sc.String[0] == '~') + { + // deprecated and ignored + sc.ScriptMessage("Deprecated option '~' found in language list"); + sc.MustGetString (); + continue; + } + if (len == 1 && sc.String[0] == '*') + { + activeMaps.Clear(); + activeMaps.Push(global_table); + } + else if (len == 7 && stricmp (sc.String, "default") == 0) + { + activeMaps.Clear(); + activeMaps.Push(default_table); + hasDefaultEntry = true; + } + else + { + sc.ScriptError ("The language code must be 2 or 3 characters long.\n'%s' is %lu characters long.", + sc.String, len); + } + } + else + { + if (activeMaps.Size() != 1 || (activeMaps[0] != default_table && activeMaps[0] != global_table)) + activeMaps.Push(MAKE_ID(tolower(sc.String[0]), tolower(sc.String[1]), tolower(sc.String[2]), 0)); + } + sc.MustGetString (); + } while (!sc.Compare ("]")); + } + else + { // Process string definitions. + if (activeMaps.Size() == 0) + { + // LANGUAGE lump is bad. We need to check if this is an old binary + // lump and if so just skip it to allow old WADs to run which contain + // such a lump. + if (!sc.isText()) + { + if (!errordone) Printf("Skipping binary 'LANGUAGE' lump.\n"); + errordone = true; + return; + } + sc.ScriptError ("Found a string without a language specified."); + } + + bool skip = false; +#if 0 // I don't think this is needed. + if (sc.Compare("$")) + { + sc.MustGetStringName("ifgame"); + sc.MustGetStringName("("); + sc.MustGetString(); + if (sc.Compare("strifeteaser")) + { + skip |= (gameinfo.gametype != GAME_Strife) || !(gameinfo.flags & GI_SHAREWARE); + } + else + { + skip |= !sc.Compare(GameTypeName()); + } + sc.MustGetStringName(")"); + sc.MustGetString(); + + } +#endif + + FName strName (sc.String); + sc.MustGetStringName ("="); + sc.MustGetString (); + FString strText (sc.String, ProcessEscapes (sc.String)); + sc.MustGetString (); + while (!sc.Compare (";")) + { + ProcessEscapes (sc.String); + strText += sc.String; + sc.MustGetString (); + } + if (!skip) + { + if (hasDefaultEntry) + { + DeleteForLabel(lumpnum, strName); + } + // Insert the string into all relevant tables. + for (auto map : activeMaps) + { + InsertString(lumpnum, map, strName, strText); + } + } + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FStringTable::DeleteString(int langid, FName label) +{ + allStrings[langid].Remove(label); +} + +//========================================================================== +// +// This deletes all older entries for a given label. This gets called +// when a string in the default table gets updated. +// +//========================================================================== + +void FStringTable::DeleteForLabel(int lumpnum, FName label) +{ + decltype(allStrings)::Iterator it(allStrings); + decltype(allStrings)::Pair *pair; + auto filenum = fileSystem.GetFileContainer(lumpnum); + + while (it.NextPair(pair)) + { + auto entry = pair->Value.CheckKey(label); + if (entry && entry->filenum < filenum) + { + pair->Value.Remove(label); + } + } + +} + +//========================================================================== +// +// +// +//========================================================================== + +void FStringTable::InsertString(int lumpnum, int langid, FName label, const FString &string) +{ + const char *strlangid = (const char *)&langid; + TableElement te = { fileSystem.GetFileContainer(lumpnum), { string, string, string, string } }; + long index; + while ((index = te.strings[0].IndexOf("@[")) >= 0) + { + auto endindex = te.strings[0].IndexOf(']', index); + if (endindex == -1) + { + Printf("Bad macro in %s : %s\n", strlangid, label.GetChars()); + break; + } + FString macroname(te.strings[0].GetChars() + index + 2, endindex - index - 2); + FStringf lookupstr("%s/%s", strlangid, macroname.GetChars()); + FStringf replacee("@[%s]", macroname.GetChars()); + FName lookupname(lookupstr.GetChars(), true); + auto replace = allMacros.CheckKey(lookupname); + for (int i = 0; i < 4; i++) + { + const char *replacement = replace? replace->Replacements[i].GetChars() : ""; + te.strings[i].Substitute(replacee, replacement); + } + } + allStrings[langid].Insert(label, te); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FStringTable::UpdateLanguage() +{ + size_t langlen = strlen(language); + + int LanguageID = (langlen < 2 || langlen > 3) ? + MAKE_ID('e', 'n', 'u', '\0') : + MAKE_ID(language[0], language[1], language[2], '\0'); + + currentLanguageSet.Clear(); + + auto checkone = [&](uint32_t lang_id) + { + auto list = allStrings.CheckKey(lang_id); + if (list && currentLanguageSet.FindEx([&](const auto &element) { return element.first == lang_id; }) == currentLanguageSet.Size()) + currentLanguageSet.Push(std::make_pair(lang_id, list)); + }; + + checkone(global_table); + checkone(LanguageID); + checkone(LanguageID & MAKE_ID(0xff, 0xff, 0, 0)); + checkone(default_table); +} + +//========================================================================== +// +// Replace \ escape sequences in a string with the escaped characters. +// +//========================================================================== + +size_t FStringTable::ProcessEscapes (char *iptr) +{ + char *sptr = iptr, *optr = iptr, c; + + while ((c = *iptr++) != '\0') + { + if (c == '\\') + { + c = *iptr++; + if (c == 'n') + c = '\n'; + else if (c == 'c') + c = TEXTCOLOR_ESCAPE; + else if (c == 'r') + c = '\r'; + else if (c == 't') + c = '\t'; + else if (c == '\n') + continue; + } + *optr++ = c; + } + *optr = '\0'; + return optr - sptr; +} + +//========================================================================== +// +// Checks if the given key exists in any one of the default string tables that are valid for all languages. +// To replace IWAD content this condition must be true. +// +//========================================================================== + +bool FStringTable::exists(const char *name) +{ + if (name == nullptr || *name == 0) + { + return false; + } + FName nm(name, true); + if (nm != NAME_None) + { + uint32_t defaultStrings[] = { default_table, global_table }; + + for (auto mapid : defaultStrings) + { + auto map = allStrings.CheckKey(mapid); + if (map) + { + auto item = map->CheckKey(nm); + if (item) return true; + } + } + } + return false; +} + +//========================================================================== +// +// Finds a string by name and returns its value +// +//========================================================================== + +const char *FStringTable::GetString(const char *name, uint32_t *langtable, int gender) const +{ + if (name == nullptr || *name == 0) + { + return nullptr; + } + if (gender == -1) gender = cl_gender; + if (gender < 0 || gender > 3) gender = 0; + FName nm(name, true); + if (nm != NAME_None) + { + for (auto map : currentLanguageSet) + { + auto item = map.second->CheckKey(nm); + if (item) + { + if (langtable) *langtable = map.first; + return item->strings[gender].GetChars(); + } + } + } + return nullptr; +} + +//========================================================================== +// +// Finds a string by name in a given language +// +//========================================================================== + +const char *FStringTable::GetLanguageString(const char *name, uint32_t langtable, int gender) const +{ + if (name == nullptr || *name == 0) + { + return nullptr; + } + if (gender == -1) gender = cl_gender; + if (gender < 0 || gender > 3) gender = 0; + FName nm(name, true); + if (nm != NAME_None) + { + auto map = allStrings.CheckKey(langtable); + if (map == nullptr) return nullptr; + auto item = map->CheckKey(nm); + if (item) + { + return item->strings[gender].GetChars(); + } + } + return nullptr; +} + +bool FStringTable::MatchDefaultString(const char *name, const char *content) const +{ + // This only compares the first line to avoid problems with bad linefeeds. For the few cases where this feature is needed it is sufficient. + auto c = GetLanguageString(name, FStringTable::default_table); + if (!c) return false; + + // Check a secondary key, in case the text comparison cannot be done due to needed orthographic fixes (see Harmony's exit text) + FStringf checkkey("%s_CHECK", name); + auto cc = GetLanguageString(checkkey, FStringTable::default_table); + if (cc) c = cc; + + return (c && !strnicmp(c, content, strcspn(content, "\n\r\t"))); +} + +//========================================================================== +// +// Finds a string by name and returns its value. If the string does +// not exist, returns the passed name instead. +// +//========================================================================== + +const char *FStringTable::operator() (const char *name) const +{ + const char *str = operator[] (name); + return str ? str : name; +} + + +//========================================================================== +// +// Find a string with the same exact text. Returns its name. +// This does not need to check genders, it is only used by +// Dehacked on the English table for finding stock strings. +// +//========================================================================== + +const char *StringMap::MatchString (const char *string) const +{ + StringMap::ConstIterator it(*this); + StringMap::ConstPair *pair; + + while (it.NextPair(pair)) + { + if (pair->Value.strings[0].CompareNoCase(string) == 0) + { + return pair->Key.GetChars(); + } + } + return nullptr; +} + +FStringTable GStrings; +CVAR(String, language, "en", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) diff --git a/source/common/utility/stringtable.h b/source/common/utility/stringtable.h new file mode 100644 index 000000000..5849d2b2c --- /dev/null +++ b/source/common/utility/stringtable.h @@ -0,0 +1,133 @@ +/* +** stringtable.h +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +** FStringTable +** +** This class manages a list of localizable strings stored in a wad file. +*/ + +#ifndef __STRINGTABLE_H__ +#define __STRINGTABLE_H__ + +#ifdef _MSC_VER +#pragma once +#endif + + +#include +#include "basics.h" +#include "zstring.h" +#include "tarray.h" +#include "name.h" + +struct TableElement +{ + int filenum; + FString strings[4]; +}; + +// This public interface is for Dehacked +class StringMap : public TMap +{ +public: + const char *MatchString(const char *string) const; +}; + + +struct StringMacro +{ + FString Replacements[4]; +}; + + +class FStringTable +{ +public: + enum : uint32_t + { + default_table = MAKE_ID('*', '*', 0, 0), + global_table = MAKE_ID('*', 0, 0, 0), + }; + + using LangMap = TMap; + using StringMacroMap = TMap; + + void LoadStrings (); + void UpdateLanguage(); + + const char *GetLanguageString(const char *name, uint32_t langtable, int gender = -1) const; + bool MatchDefaultString(const char *name, const char *content) const; + const char *GetString(const char *name, uint32_t *langtable, int gender = -1) const; + const char *operator() (const char *name) const; // Never returns NULL + const char *operator[] (const char *name) const + { + return GetString(name, nullptr); + } + bool exists(const char *name); + +private: + + StringMacroMap allMacros; + LangMap allStrings; + TArray> currentLanguageSet; + + void LoadLanguage (int lumpnum, const TArray &buffer); + TArray> parseCSV(const TArray &buffer); + bool ParseLanguageCSV(int lumpnum, const TArray &buffer); + + bool LoadLanguageFromSpreadsheet(int lumpnum, const TArray &buffer); + bool readMacros(int lumpnum); + void InsertString(int lumpnum, int langid, FName label, const FString &string); + void DeleteString(int langid, FName label); + void DeleteForLabel(int lumpnum, FName label); + + static size_t ProcessEscapes (char *str); +public: + static FString MakeMacro(const char *str) + { + if (*str == '$') return str; + return FString("$") + str; + } + + static FString MakeMacro(const char *str, size_t len) + { + if (*str == '$') return FString(str, len); + return "$" + FString(str, len); + } + + const char* localize(const char* str) + { + return *str == '$' ? operator()(str + 1) : str; + } +}; + +#endif //__STRINGTABLE_H__ diff --git a/source/common/utility/tarray.h b/source/common/utility/tarray.h index 77265ece8..2be5f882a 100644 --- a/source/common/utility/tarray.h +++ b/source/common/utility/tarray.h @@ -237,14 +237,17 @@ public: } return true; } - // Return a reference to an element + // Return a reference to an element. + // Note that the asserts must let the element after the end pass because this gets frequently used as a sentinel pointer. T &operator[] (size_t index) const { + assert(index <= Count); return Array[index]; } // Returns the value of an element TT operator() (size_t index) const { + assert(index <= Count); return Array[index]; } // Returns a reference to the last element diff --git a/source/common/version.h b/source/common/version.h index 388737dbf..c9908ab51 100644 --- a/source/common/version.h +++ b/source/common/version.h @@ -41,11 +41,11 @@ const char *GetVersionString(); /** Lots of different version numbers **/ -#define VERSIONSTR "0.0.1" +#define VERSIONSTR "0.1.0" // The version as seen in the Windows resource -#define RC_FILEVERSION 0,0,1,0 -#define RC_PRODUCTVERSION 0,0,1,0 +#define RC_FILEVERSION 0,1,0,0 +#define RC_PRODUCTVERSION 0,1,0,0 #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 0 @@ -59,6 +59,21 @@ const char *GetVersionString(); #define FORUM_URL "http://forum.zdoom.org/" //#define BUGS_FORUM_URL "http://forum.zdoom.org/viewforum.php?f=2" +#define SAVESIG_DN3D "Demolition.Duke" +#define SAVESIG_BLD "Demolition.Blood" +#define SAVESIG_RR "Demolition.Redneck" +#define SAVESIG_SW "Demolition.SW" + +#define MINSAVEVER_DN3D 1 +#define MINSAVEVER_BLD 1 +#define MINSAVEVER_RR 1 +#define MINSAVEVER_SW 1 + +#define SAVEVER_DN3D 1 +#define SAVEVER_BLD 1 +#define SAVEVER_RR 1 +#define SAVEVER_SW 1 + #if defined(__APPLE__) || defined(_WIN32) #define GAME_DIR GAMENAME #else diff --git a/source/duke3d/CMakeLists.txt b/source/duke3d/CMakeLists.txt index c0619e2cb..b3169684e 100644 --- a/source/duke3d/CMakeLists.txt +++ b/source/duke3d/CMakeLists.txt @@ -62,8 +62,9 @@ set( PCH_SOURCES src/sector.cpp src/sounds.cpp src/soundsdyn.cpp + src/d_menu.cpp ) - + if( MSVC ) enable_precompiled_headers( ../g_pch.h PCH_SOURCES ) # The original Build code was written with unsigned chars and unfortunately they still haven't been eliminated entirely. diff --git a/source/duke3d/src/actors.cpp b/source/duke3d/src/actors.cpp index 83871ebde..d7e43c61f 100644 --- a/source/duke3d/src/actors.cpp +++ b/source/duke3d/src/actors.cpp @@ -7988,13 +7988,13 @@ next_sprite: static void G_DoEffectorLights(void) // STATNUM 14 { - int32_t i; +#ifdef POLYMER + int32_t i; for (SPRITES_OF(STAT_LIGHT, i)) { - switch (sprite[i].lotag) + switch (sprite[i].lotag) { -#ifdef POLYMER case SE_49_POINT_LIGHT: { if (!A_CheckSpriteFlags(i, SFLAG_NOLIGHT) && videoGetRenderMode() == REND_POLYMER && @@ -8156,9 +8156,9 @@ static void G_DoEffectorLights(void) // STATNUM 14 break; } -#endif // POLYMER } } +#endif // POLYMER } #ifdef POLYMER diff --git a/source/duke3d/src/anim.cpp b/source/duke3d/src/anim.cpp index a0a0e2e02..3af7e8d8d 100644 --- a/source/duke3d/src/anim.cpp +++ b/source/duke3d/src/anim.cpp @@ -253,7 +253,7 @@ int32_t Anim_Play(const char *fn) FileReader handle; if (!Bstrcmp(dot, ".ivf")) { - handle = kopenFileReader(fn, 0); + handle = fileSystem.OpenFileReader(fn, 0); if (!handle.isOpen()) break; } @@ -272,7 +272,7 @@ int32_t Anim_Play(const char *fn) vpxfndot[3] = 'f'; vpxfndot[4] = '\0'; - handle = kopenFileReader(vpxfn, 0); + handle = fileSystem.OpenFileReader(vpxfn, 0); if (!handle.isOpen()) break; @@ -420,7 +420,7 @@ int32_t Anim_Play(const char *fn) int32_t ogltexfiltermode = hw_texfilter; #endif TArray buffer; - auto fr = kopenFileReader(fn, 0); + auto fr = fileSystem.OpenFileReader(fn, 0); if (!fr.isOpen()) goto end_anim; diff --git a/source/duke3d/src/cheats.cpp b/source/duke3d/src/cheats.cpp index 13feb226d..ff4d030d5 100644 --- a/source/duke3d/src/cheats.cpp +++ b/source/duke3d/src/cheats.cpp @@ -22,9 +22,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "ns.h" // Must come before everything else! +#include "cheats.h" + #include "duke3d.h" #include "osdcmds.h" -#include "cheats.h" +#include "mapinfo.h" BEGIN_DUKE_NS @@ -187,9 +189,6 @@ void G_SetupCheats(void) Bstrcpy(CheatStrings[23], ""); Bstrcpy(CheatStrings[24], "2debug"); Bstrcpy(CheatStrings[26], "2cgs"); - - Bstrcpy(g_gametypeNames[0], "GI Match (Spawn)"); - Bstrcpy(g_gametypeNames[2], "GI Match (No Spawn)"); } else if (NAM) { @@ -219,9 +218,6 @@ void G_SetupCheats(void) Bstrcpy(CheatStrings[23], ""); Bstrcpy(CheatStrings[24], "adebug"); Bstrcpy(CheatStrings[26], "acgs"); - - Bstrcpy(g_gametypeNames[0], "GruntMatch (Spawn)"); - Bstrcpy(g_gametypeNames[2], "GruntMatch (No Spawn)"); } } #endif @@ -248,10 +244,11 @@ static void G_CheatGetInv(DukePlayer_t *pPlayer) static void end_cheat(DukePlayer_t * const pPlayer) { pPlayer->cheat_phase = 0; + g_cheatBufLen = 0; inputState.keyFlushChars(); } -static int32_t cheatbuflen; +int g_cheatBufLen; static int8_t cheatbuf[MAXCHEATLEN]; void G_DoCheats(void) @@ -317,31 +314,33 @@ void G_DoCheats(void) if (!((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'))) { pPlayer->cheat_phase = 0; + g_cheatBufLen = 0; // P_DoQuote(QUOTE_46,pPlayer); return; } - cheatbuf[cheatbuflen++] = (int8_t) ch; + cheatbuf[g_cheatBufLen++] = (int8_t) ch; // This assertion is not obvious, but it should hold because of the // cheat string matching logic below. - Bassert(cheatbuflen < (signed)sizeof(cheatbuf)); - cheatbuf[cheatbuflen] = 0; + Bassert(g_cheatBufLen < (signed)sizeof(cheatbuf)); + cheatbuf[g_cheatBufLen] = 0; // inputState.ClearKeysDown(); for (cheatNum=0; cheatNum < NUMCHEATCODES; cheatNum++) { - for (bssize_t j = 0; j= '0' && ch <= '9')) { if (CheatStrings[cheatNum][j+1] == 0) goto FOUNDCHEAT; - if (j == cheatbuflen-1) return; + if (j == g_cheatBufLen-1) return; } else break; } } pPlayer->cheat_phase = 0; + g_cheatBufLen = 0; return; FOUNDCHEAT:; @@ -464,8 +463,7 @@ void G_DoCheats(void) case CHEAT_ALLEN: P_DoQuote(QUOTE_CHEAT_ALLEN, pPlayer); - pPlayer->cheat_phase = 0; - inputState.ClearKeyStatus(sc_N); + end_cheat(pPlayer); return; case CHEAT_CORNHOLIO: @@ -499,7 +497,7 @@ void G_DoCheats(void) } else { - Bstrcpy(apStrings[QUOTE_RESERVED4], "Come Get Some!"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "$COMEGETSOME"); S_PlaySound(DUKE_GETWEAPON2); P_DoQuote(QUOTE_RESERVED4, pPlayer); @@ -558,7 +556,7 @@ void G_DoCheats(void) int32_t const volnume = ud.m_volume_number, levnume = m_level_number; if ((!VOLUMEONE || volnume == 0) && (unsigned)volnume < (unsigned)g_volumeCnt && - (unsigned)levnume < MAXLEVELS && g_mapInfo[volnume*MAXLEVELS + levnume].filename != NULL) + (unsigned)levnume < MAXLEVELS && mapList[volnume*MAXLEVELS + levnume].fileName.IsNotEmpty()) { ud.volume_number = volnume; ud.level_number = levnume; @@ -628,8 +626,7 @@ void G_DoCheats(void) case CHEAT_CASHMAN: ud.cashman = 1-ud.cashman; - inputState.ClearKeyStatus(sc_N); - pPlayer->cheat_phase = 0; + end_cheat(pPlayer); return; case CHEAT_ITEMS: @@ -654,7 +651,7 @@ void G_DoCheats(void) case CHEAT_TODD: if (NAM) { - Bstrcpy(apStrings[QUOTE_RESERVED4], CheatDescriptions[CHEAT_TODD]); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, CheatDescriptions[CHEAT_TODD]); P_DoQuote(QUOTE_RESERVED4, pPlayer); } else @@ -672,7 +669,6 @@ void G_DoCheats(void) case CHEAT_BETA: P_DoQuote(QUOTE_CHEAT_BETA, pPlayer); - inputState.ClearKeyStatus(sc_H); end_cheat(pPlayer); return; @@ -685,12 +681,12 @@ void G_DoCheats(void) case CHEAT_MONSTERS: { - const char *s [] = { "On", "Off", "On (2)" }; + const char *s [] = { "OPTVAL_ON", "OPTVAL_OFF", "$TXT_ON2" }; if (++g_noEnemies == 3) g_noEnemies = 0; - Bsprintf(apStrings[QUOTE_RESERVED4], "Monsters: %s", s[g_noEnemies]); + quoteMgr.FormatQuote(QUOTE_RESERVED4, "%s: %s", GStrings("NETMNU_MONSTERS"), s[g_noEnemies]); P_DoQuote(QUOTE_RESERVED4, pPlayer); end_cheat(pPlayer); @@ -701,8 +697,8 @@ void G_DoCheats(void) case CHEAT_RESERVED3: ud.eog = 1; pPlayer->player_par = 0; - pPlayer->gm |= MODE_EOL; - inputState.keyFlushChars(); + pPlayer->gm |= MODE_EOL;; + end_cheat(pPlayer); return; default: @@ -737,13 +733,14 @@ void G_DoCheats(void) { pPlayer->cheat_phase = 1; // P_DoQuote(QUOTE_25,pPlayer); - cheatbuflen = 0; } + g_cheatBufLen = 0; inputState.keyFlushChars(); } else if (pPlayer->cheat_phase != 0) { pPlayer->cheat_phase = 0; + g_cheatBufLen = 0; inputState.ClearKeyStatus((uint8_t) CheatKeys[0]); inputState.ClearKeyStatus((uint8_t) CheatKeys[1]); } diff --git a/source/duke3d/src/cheats.h b/source/duke3d/src/cheats.h index 385aa1c51..aec829785 100644 --- a/source/duke3d/src/cheats.h +++ b/source/duke3d/src/cheats.h @@ -28,8 +28,9 @@ BEGIN_DUKE_NS #define MAXCHEATDESC 64 #define NUMCHEATCODES (int32_t) ARRAY_SIZE(CheatStrings) -extern void G_DoCheats(void); -extern void G_SetupCheats(void); +void G_DoCheats(void); +void G_SetupCheats(void); +extern int g_cheatBufLen; enum cheatindex_t { diff --git a/source/duke3d/src/common.cpp b/source/duke3d/src/common.cpp index 74f0e56ad..ff6be1845 100644 --- a/source/duke3d/src/common.cpp +++ b/source/duke3d/src/common.cpp @@ -106,7 +106,7 @@ void G_LoadLookups(void) { int32_t j; - auto fr = kopenFileReader("lookup.dat", 0); + auto fr = fileSystem.OpenFileReader("lookup.dat", 0); if (!fr.isOpen()) return; diff --git a/source/duke3d/src/config.cpp b/source/duke3d/src/config.cpp index 886984031..93d36764a 100644 --- a/source/duke3d/src/config.cpp +++ b/source/duke3d/src/config.cpp @@ -74,7 +74,6 @@ void CONFIG_SetDefaults(void) ud.angleinterpolation = 0; ud.camerasprite = -1; ud.config.ShowWeapons = 0; - ud.default_skill = 1; ud.display_bonus_screen = 1; hud_position = 0; diff --git a/source/duke3d/src/d_menu.cpp b/source/duke3d/src/d_menu.cpp new file mode 100644 index 000000000..38e3822bf --- /dev/null +++ b/source/duke3d/src/d_menu.cpp @@ -0,0 +1,801 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2016 EDuke32 developers and contributors +Copyright (C) 2019 Christoph Oelckers + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- + +#include "ns.h" // Must come before everything else! + +#include "cheats.h" +#include "compat.h" +#include "demo.h" +#include "duke3d.h" +#include "input.h" +#include "menus.h" +#include "osdcmds.h" +#include "savegame.h" +#include "game.h" +#include "superfasthash.h" +#include "gamecvars.h" +#include "gamecontrol.h" +#include "c_bind.h" +#include "menu/menu.h" +#include "gstrings.h" +#include "version.h" +#include "namesdyn.h" +#include "menus.h" +#include "../../glbackend/glbackend.h" + +BEGIN_DUKE_NS + +#define MENU_MARGIN_REGULAR 40 +#define MENU_MARGIN_WIDE 32 +#define MENU_MARGIN_CENTER 160 +#define MENU_HEIGHT_CENTER 100 + + +enum MenuTextFlags_t +{ + MT_Selected = 1 << 0, + MT_Disabled = 1 << 1, + MT_XCenter = 1 << 2, + MT_XRight = 1 << 3, + MT_YCenter = 1 << 4, + MT_Literal = 1 << 5, + MT_RightSide = 1 << 6, +}; + + +// common font types +// tilenums are set after namesdyn runs. +// These are also modifiable by scripts. +// emptychar x,y between x,y zoom cursorLeft cursorCenter cursorScale textflags +// tilenum shade_deselected shade_disabled pal pal_selected pal_deselected pal_disabled +MenuFont_t MF_Redfont = { { 5<<16, 15<<16 }, { 0, 0 }, 65536, 20<<16, 110<<16, 65536, TEXT_BIGALPHANUM | TEXT_UPPERCASE, + -1, 10, 0, 0, 0, 0, 1, + 0, 0, 1 }; +MenuFont_t MF_Bluefont = { { 5<<16, 7<<16 }, { 0, 0 }, 65536, 10<<16, 110<<16, 32768, 0, + -1, 10, 0, 0, 10, 10, 16, + 0, 0, 16 }; +MenuFont_t MF_Minifont = { { 4<<16, 5<<16 }, { 1<<16, 1<<16 }, 65536, 10<<16, 110<<16, 32768, 0, + -1, 10, 0, 0, 2, 2, 0, + 0, 0, 16 }; + + +/* +This function prepares data after ART and CON have been processed. +It also initializes some data in loops rather than statically at compile time. +*/ +void Menu_Init(void) +{ + + // prepare menu fonts + // check if tilenum is -1 in case it was set in EVENT_SETDEFAULTS + if ((unsigned)MF_Redfont.tilenum >= MAXTILES) MF_Redfont.tilenum = BIGALPHANUM; + if ((unsigned)MF_Bluefont.tilenum >= MAXTILES) MF_Bluefont.tilenum = STARTALPHANUM; + if ((unsigned)MF_Minifont.tilenum >= MAXTILES) MF_Minifont.tilenum = MINIFONT; + MF_Redfont.emptychar.y = tilesiz[MF_Redfont.tilenum].y << 16; + MF_Bluefont.emptychar.y = tilesiz[MF_Bluefont.tilenum].y << 16; + MF_Minifont.emptychar.y = tilesiz[MF_Minifont.tilenum].y << 16; + if (!minitext_lowercase) + MF_Minifont.textflags |= TEXT_UPPERCASE; + +#if 0 + + // prepare sound setup +#ifndef EDUKE32_STANDALONE + if (WW2GI) + ME_SOUND_DUKETALK.name = "GI talk:"; + else if (NAM) + ME_SOUND_DUKETALK.name = "Grunt talk:"; +#endif + + + // prepare shareware + if (VOLUMEONE) + { + // blue out episodes beyond the first + for (i = 1; i < g_volumeCnt; ++i) + { + if (MEL_EPISODE[i]) + { + ME_EPISODE[i].entry = &MEO_EPISODE_SHAREWARE; + ME_EPISODE[i].flags |= MEF_LookDisabled; + } + } + M_EPISODE.numEntries = g_volumeCnt; // remove User Map (and spacer) + MEOS_NETOPTIONS_EPISODE.numOptions = 1; + MenuEntry_DisableOnCondition(&ME_NETOPTIONS_EPISODE, 1); + } + + // prepare pre-Atomic + if (!VOLUMEALL || !PLUTOPAK) + { + // prepare credits + M_CREDITS.title = M_CREDITS2.title = M_CREDITS3.title = s_Credits; + } + + +#endif +} + +static void Menu_DrawBackground(const DVector2 &origin) +{ + rotatesprite_fs(int(origin.X * 65536) + (MENU_MARGIN_CENTER << 16), int(origin.Y * 65536) + (100 << 16), 65536L, 0, MENUSCREEN, 16, 0, 10 + 64); +} + +static void Menu_DrawTopBar(const DVector2 &origin) +{ + if ((G_GetLogoFlags() & LOGO_NOTITLEBAR) == 0) + rotatesprite_fs(int(origin.X*65536) + (MENU_MARGIN_CENTER<<16), int(origin.Y*65536) + (19<<16), MF_Redfont.cursorScale, 0,MENUBAR,16,0,10); +} + +static void Menu_DrawTopBarCaption(const char *caption, const DVector2 &origin) +{ + static char t[64]; + size_t const srclen = strlen(caption); + size_t const dstlen = min(srclen, ARRAY_SIZE(t)-1); + memcpy(t, caption, dstlen); + t[dstlen] = '\0'; + char *p = &t[dstlen-1]; + if (*p == ':') + *p = '\0'; + captionmenutext(int(origin.X*65536) + (MENU_MARGIN_CENTER<<16), int(origin.Y*65536) + (24<<16) + ((15>>1)<<16), t); +} + +static void Menu_GetFmt(const MenuFont_t* font, uint8_t const status, int32_t* s, int32_t* z) +{ + if (status & MT_Selected) + *s = VM_OnEventWithReturn(EVENT_MENUSHADESELECTED, -1, myconnectindex, sintable[((int32_t)totalclock << 5) & 2047] >> 12); + else + *s = font->shade_deselected; + // sum shade values + if (status & MT_Disabled) + *s += font->shade_disabled; + + if (FURY && status & MT_Selected) + *z += (*z >> 4); +} + +static vec2_t Menu_Text(int32_t x, int32_t y, const MenuFont_t* font, const char* t, uint8_t status, int32_t ydim_upper, int32_t ydim_lower) +{ + int32_t s, p, ybetween = font->between.y; + int32_t f = font->textflags; + if (status & MT_XCenter) + f |= TEXT_XCENTER; + if (status & MT_XRight) + f |= TEXT_XRIGHT; + if (status & MT_YCenter) + { + f |= TEXT_YCENTER | TEXT_YOFFSETZERO; + ybetween = font->emptychar.y; // <^ the battle against 'Q' + } + if (status & MT_Literal) + f |= TEXT_LITERALESCAPE; + + int32_t z = font->zoom; + + if (status & MT_Disabled) + p = (status & MT_RightSide) ? font->pal_disabled_right : font->pal_disabled; + else if (status & MT_Selected) + p = (status & MT_RightSide) ? font->pal_selected_right : font->pal_selected; + else + p = (status & MT_RightSide) ? font->pal_deselected_right : font->pal_deselected; + + Menu_GetFmt(font, status, &s, &z); + + return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim - 1, ydim_lower); +} + +static vec2_t mgametextcenterat(int32_t x, int32_t y, char const* t, int32_t f = 0) +{ + return G_ScreenText(MF_Bluefont.tilenum, x, y, MF_Bluefont.zoom, 0, 0, t, 0, MF_Bluefont.pal, 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags | f | TEXT_XCENTER, 0, 0, xdim - 1, ydim - 1); +} +static vec2_t mgametextcenter(int32_t x, int32_t y, char const* t, int32_t f = 0) +{ + return mgametextcenterat((MENU_MARGIN_CENTER << 16) + x, y, t, f); +} + +static int32_t Menu_CursorShade(void) +{ + return VM_OnEventWithReturn(EVENT_MENUCURSORSHADE, -1, myconnectindex, 4 - (sintable[((int32_t)totalclock << 4) & 2047] >> 11)); +} + +static void Menu_DrawCursorCommon(int32_t x, int32_t y, int32_t z, int32_t picnum, int32_t ydim_upper = 0, int32_t ydim_lower = ydim - 1) +{ + rotatesprite_(x, y, z, 0, picnum, Menu_CursorShade(), 0, 2 | 8, 0, 0, 0, ydim_upper, xdim - 1, ydim_lower); +} + +static void Menu_DrawCursorLeft(int32_t x, int32_t y, int32_t z) +{ + if (FURY) return; + Menu_DrawCursorCommon(x, y, z, VM_OnEventWithReturn(EVENT_MENUCURSORLEFT, -1, myconnectindex, SPINNINGNUKEICON + (((int32_t)totalclock >> 3) % 7))); +} + +static void Menu_DrawCursorRight(int32_t x, int32_t y, int32_t z) +{ + if (FURY) return; + Menu_DrawCursorCommon(x, y, z, VM_OnEventWithReturn(EVENT_MENUCURSORRIGHT, -1, myconnectindex, SPINNINGNUKEICON + 6 - ((6 + ((int32_t)totalclock >> 3)) % 7))); +} + +static int Menu_GetFontHeight(int fontnum) +{ + auto& font = fontnum == NIT_BigFont ? MF_Redfont : fontnum == NIT_SmallFont ? MF_Bluefont : MF_Minifont; + return font.get_yline(); +} + +//---------------------------------------------------------------------------- +// +// Implements the native looking menu used for the main menu +// and the episode/skill selection screens, i.e. the parts +// that need to look authentic +// +//---------------------------------------------------------------------------- + +class DukeListMenu : public DListMenu +{ + using Super = DListMenu; +protected: + + void SelectionChanged() override + { + if (mDesc->mScriptId == 110) + { + // Hack alert: Ion Fury depends on the skill getting set globally when the selection changes because the script cannot detect actual selection changes. + // Yuck! + ud.m_player_skill = mDesc->mSelectedItem+1; + } + } + + virtual void CallScript(int event, bool getorigin = false) + { + ud.returnvar[0] = int(origin.X * 65536); + ud.returnvar[1] = int(origin.Y * 65536); + ud.returnvar[2] = mDesc->mSelectedItem; + VM_OnEventWithReturn(event, g_player[screenpeek].ps->i, screenpeek, mDesc->mScriptId); + if (getorigin) + { + origin.X = ud.returnvar[0] / 65536.; + origin.Y = ud.returnvar[1] / 65536.; + } + } + + void Ticker() override + { + auto lf = G_GetLogoFlags(); + help_disabled = (lf & LOGO_NOHELP); + credits_disabled = (lf & LOGO_NOCREDITS); + + // Lay out the menu. Since scripts are allowed to mess around with the font this needs to be redone each frame. + int32_t y_upper = mDesc->mYpos; + int32_t y_lower = y_upper + mDesc->mYbotton; + int32_t y = 0; + int32_t calculatedentryspacing = 0; + int32_t const height = Menu_GetFontHeight(mDesc->mNativeFontNum) >> 16; + + int32_t totalheight = 0, numvalidentries = mDesc->mItems.Size(); + + for (unsigned e = 0; e < mDesc->mItems.Size(); ++e) + { + auto entry = mDesc->mItems[e]; + entry->mHidden = false; + if (entry->GetAction(nullptr) == NAME_HelpMenu && help_disabled) + { + entry->mHidden = true; + numvalidentries--; + continue; + } + else if (entry->GetAction(nullptr) == NAME_CreditsMenu && credits_disabled) + { + entry->mHidden = true; + numvalidentries--; + continue; + } + entry->SetHeight(height); + totalheight += height; + } + if (mDesc->mSpacing <= 0) calculatedentryspacing = std::max(0, (y_lower - y_upper - totalheight) / (numvalidentries > 1 ? numvalidentries - 1 : 1)); + if (calculatedentryspacing <= 0) calculatedentryspacing = mDesc->mSpacing; + + + // totalHeight calculating pass + int totalHeight; + for (unsigned e = 0; e < mDesc->mItems.Size(); ++e) + { + auto entry = mDesc->mItems[e]; + if (!entry->mHidden) + { + entry->SetY(y_upper + y); + y += height; + totalHeight = y; + y += calculatedentryspacing; + } + } + } + + void PreDraw() override + { + CallScript(CurrentMenu == this ? EVENT_DISPLAYMENU : EVENT_DISPLAYINACTIVEMENU, true); + Super::PreDraw(); + } + + void PostDraw() override + { + CallScript(CurrentMenu == this ? EVENT_DISPLAYMENUREST : EVENT_DISPLAYINACTIVEMENUREST, false); + } +}; + +class DukeNewGameCustomSubMenu : public DukeListMenu +{ + virtual void CallScript(int event, bool getorigin) override + { + // This needs to get the secondary ID to the script. + ud.returnvar[3] = mDesc->mSecondaryId; + DukeListMenu::CallScript(event, getorigin); + } +}; + +class DukeMainMenu : public DukeListMenu +{ + void PreDraw() override + { + DukeListMenu::PreDraw(); + if ((G_GetLogoFlags() & LOGO_NOGAMETITLE) == 0) + { + rotatesprite_fs(int(origin.X * 65536) + (MENU_MARGIN_CENTER<<16), int(origin.Y * 65536) + ((28)<<16), 65536L,0,INGAMEDUKETHREEDEE,0,0,10); + if (PLUTOPAK) // JBF 20030804 + rotatesprite_fs(int(origin.X * 65536) + ((MENU_MARGIN_CENTER+100)<<16), int(origin.Y * 65536) + (36<<16), 65536L,0,PLUTOPAKSPRITE+2,(sintable[((int32_t) totalclock<<4)&2047]>>11),0,2+8); + } + } +}; + +//---------------------------------------------------------------------------- +// +// Hack to display Ion Fury's credits screens +// +//---------------------------------------------------------------------------- + +class DukeImageScreen : public ImageScreen +{ +public: + DukeImageScreen(FImageScrollerDescriptor::ScrollerItem* desc) + : ImageScreen(desc) + {} + + void CallScript(int event, bool getorigin = false) + { + ud.returnvar[0] = int(origin.X * 65536); + ud.returnvar[1] = int(origin.Y * 65536); + ud.returnvar[2] = 0; + VM_OnEventWithReturn(event, g_player[screenpeek].ps->i, screenpeek, mDesc->scriptID); + if (getorigin) + { + origin.X = ud.returnvar[0] / 65536.; + origin.Y = ud.returnvar[1] / 65536.; + } + } + + void Drawer() override + { + // Hack alert: The Ion Fury scripts - being true to the entire design here, take the current menu value + // not from the passed variable but instead from the global current_menu, so we have to temporarily alter that here. + // Ugh. (Talk about "broken by design"...) + auto cm = g_currentMenu; + g_currentMenu = mDesc->scriptID; + auto o = origin; + CallScript(EVENT_DISPLAYMENU, true); + ImageScreen::Drawer(); + CallScript(EVENT_DISPLAYMENUREST, false); + g_currentMenu = cm; + origin = o; + } +}; + +class DDukeImageScrollerMenu : public DImageScrollerMenu +{ + ImageScreen* newImageScreen(FImageScrollerDescriptor::ScrollerItem* desc) override + { + return new DukeImageScreen(desc); + } +}; + +//---------------------------------------------------------------------------- +// +// Menu related game interface functions +// +//---------------------------------------------------------------------------- + +void GameInterface::DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) +{ + int ydim_upper = 0; + int ydim_lower = ydim - 1; + //int32_t const indent = 0; // not set for any relevant menu + int x = int(xpos * 65536); + + uint8_t status = 0; + if (state == NIT_SelectedState) + status |= MT_Selected; + if (state == NIT_InactiveState) + status |= MT_Disabled; + if (flags & LMF_Centered) + status |= MT_XCenter; + + bool const dodraw = true; + MenuFont_t& font = fontnum == NIT_BigFont ? MF_Redfont : fontnum == NIT_SmallFont ? MF_Bluefont : MF_Minifont; + + int32_t const height = font.get_yline(); + status |= MT_YCenter; + int32_t const y_internal = int(ypos * 65536) + ((height >> 17) << 16);// -menu->scrollPos; + + vec2_t textsize; + if (dodraw) + textsize = Menu_Text(x, y_internal, &font, text, status, ydim_upper, ydim_lower); + + if (dodraw && (status & MT_Selected) && state != 1) + { + if (status & MT_XCenter) + { + Menu_DrawCursorLeft(x + font.cursorCenterPosition, y_internal, font.cursorScale); + Menu_DrawCursorRight(x - font.cursorCenterPosition, y_internal, font.cursorScale); + } + else + Menu_DrawCursorLeft(x /*+ indent*/ - font.cursorLeftPosition, y_internal, font.cursorScale); + } + +} + +void GameInterface::MenuOpened() +{ + S_PauseSounds(true); + if ((!g_netServer && ud.multimode < 2)) + { + ready2send = 0; + totalclock = ototalclock; + screenpeek = myconnectindex; + } + + auto& gm = g_player[myconnectindex].ps->gm; + if (gm & MODE_GAME) + { + gm |= MODE_MENU; + } +} + +void GameInterface::MenuSound(EMenuSounds snd) +{ + switch (snd) + { + case CursorSound: + S_PlaySound(KICK_HIT); + break; + + case AdvanceSound: + S_PlaySound(PISTOL_BODYHIT); + break; + + case CloseSound: + S_PlaySound(EXITMENUSOUND); + break; + + default: + return; + } +} + + +void GameInterface::MenuClosed() +{ + + auto& gm = g_player[myconnectindex].ps->gm; + if (gm & MODE_GAME) + { + if (gm & MODE_MENU) + I_ClearAllInput(); + + // The following lines are here so that you cannot close the menu when no game is running. + gm &= ~MODE_MENU; + + if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) + { + ready2send = 1; + totalclock = ototalclock; + CAMERACLOCK = (int32_t)totalclock; + CAMERADIST = 65536; + + // Reset next-viewscreen-redraw counter. + // XXX: are there any other cases like that in need of handling? + if (g_curViewscreen >= 0) + actor[g_curViewscreen].t_data[0] = (int32_t)totalclock; + } + + G_UpdateScreenArea(); + S_PauseSounds(false); + } +} + +bool GameInterface::CanSave() +{ + if (ud.recstat == 2) return false; + auto &myplayer = *g_player[myconnectindex].ps; + if (sprite[myplayer.i].extra <= 0) + { + P_DoQuote(QUOTE_SAVE_DEAD, &myplayer); + return false; + } + return true; +} + +void GameInterface::CustomMenuSelection(int menu, int item) +{ + ud.returnvar[0] = item; + ud.returnvar[1] = -1; + VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, menu); +} + +void GameInterface::StartGame(FGameStartup& gs) +{ + int32_t skillsound = PISTOL_BODYHIT; + + switch (gs.Skill) + { + case 0: + skillsound = JIBBED_ACTOR6; + break; + case 1: + skillsound = BONUS_SPEECH1; + break; + case 2: + skillsound = DUKE_GETWEAPON2; + break; + case 3: + skillsound = JIBBED_ACTOR5; + break; + } + + ud.m_player_skill = gs.Skill + 1; + if (menu_sounds) ud.skill_voice = S_PlaySound(skillsound); + ud.m_respawn_monsters = (gs.Skill == 3); + ud.m_monsters_off = ud.monsters_off = 0; + ud.m_respawn_items = 0; + ud.m_respawn_inventory = 0; + ud.multimode = 1; + ud.m_volume_number = gs.Episode; + m_level_number = gs.Level; + G_NewGame_EnterLevel(); + +} + +FSavegameInfo GameInterface::GetSaveSig() +{ + return { SAVESIG_DN3D, MINSAVEVER_DN3D, SAVEVER_DN3D }; +} + + +void GameInterface::DrawMenuCaption(const DVector2& origin, const char* text) +{ + Menu_DrawTopBar(origin); + Menu_DrawTopBarCaption(text, origin); +} + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- + +static void shadowminitext(int32_t x, int32_t y, const char* t, int32_t p) +{ + int32_t f = 0; + + if (!minitext_lowercase) + f |= TEXT_UPPERCASE; + + G_ScreenTextShadow(1, 1, MINIFONT, x, y, 65536, 0, 0, t, 0, p, 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, 4 << 16, 8 << 16, 1 << 16, 0, f, 0, 0, xdim - 1, ydim - 1); +} + +//---------------------------------------------------------------------------- +// +// allows the front end to override certain fullscreen image menus +// with custom implementations. +// +// This is needed because the credits screens in Duke Nukem +// are eithrr done by providing an image or by printing text, based on the version used. +// +//---------------------------------------------------------------------------- + +bool GameInterface::DrawSpecialScreen(const DVector2 &origin, int tilenum) +{ + // Older versions of Duke Nukem create the credits screens manually. + // On the latest version there's real graphics for this. + bool haveCredits = VOLUMEALL && PLUTOPAK; + + int32_t m, l; + if (!haveCredits) + { + if (tilenum == CREDITSTEXT1) + { + Menu_DrawBackground(origin); + m = int(origin.X * 65536) + (20 << 16); + l = int(origin.Y * 65536) + (33 << 16); + + shadowminitext(m, l, "Original Concept", 12); l += 7 << 16; + shadowminitext(m, l, "Todd Replogle and Allen H. Blum III", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Produced & Directed By", 12); l += 7 << 16; + shadowminitext(m, l, "Greg Malone", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Executive Producer", 12); l += 7 << 16; + shadowminitext(m, l, "George Broussard", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "BUILD Engine", 12); l += 7 << 16; + shadowminitext(m, l, "Ken Silverman", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Game Programming", 12); l += 7 << 16; + shadowminitext(m, l, "Todd Replogle", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "3D Engine/Tools/Net", 12); l += 7 << 16; + shadowminitext(m, l, "Ken Silverman", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Network Layer/Setup Program", 12); l += 7 << 16; + shadowminitext(m, l, "Mark Dochtermann", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Map Design", 12); l += 7 << 16; + shadowminitext(m, l, "Allen H. Blum III", 12); l += 7 << 16; + shadowminitext(m, l, "Richard Gray", 12); l += 7 << 16; + + m = int(origin.X * 65536) + (180 << 16); + l = int(origin.Y * 65536) + (33 << 16); + + shadowminitext(m, l, "3D Modeling", 12); l += 7 << 16; + shadowminitext(m, l, "Chuck Jones", 12); l += 7 << 16; + shadowminitext(m, l, "Sapphire Corporation", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Artwork", 12); l += 7 << 16; + shadowminitext(m, l, "Dirk Jones, Stephen Hornback", 12); l += 7 << 16; + shadowminitext(m, l, "James Storey, David Demaret", 12); l += 7 << 16; + shadowminitext(m, l, "Douglas R. Wood", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Sound Engine", 12); l += 7 << 16; + shadowminitext(m, l, "Jim Dose", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Sound & Music Development", 12); l += 7 << 16; + shadowminitext(m, l, "Robert Prince", 12); l += 7 << 16; + shadowminitext(m, l, "Lee Jackson", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Voice Talent", 12); l += 7 << 16; + shadowminitext(m, l, "Lani Minella - Voice Producer", 12); l += 7 << 16; + shadowminitext(m, l, "Jon St. John as \"Duke Nukem\"", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Graphic Design", 12); l += 7 << 16; + shadowminitext(m, l, "Packaging, Manual, Ads", 12); l += 7 << 16; + shadowminitext(m, l, "Robert M. Atkins", 12); l += 7 << 16; + shadowminitext(m, l, "Michael Hadwin", 12); l += 7 << 16; + return true; + } + else if (tilenum == CREDITSTEXT2__STATIC) + { + Menu_DrawBackground(origin); + m = int(origin.X * 65536) + (20 << 16); + l = int(origin.Y * 65536) + (33 << 16); + + shadowminitext(m, l, "Special Thanks To", 12); l += 7 << 16; + shadowminitext(m, l, "Steven Blackburn, Tom Hall", 12); l += 7 << 16; + shadowminitext(m, l, "Scott Miller, Joe Siegler", 12); l += 7 << 16; + shadowminitext(m, l, "Terry Nagy, Colleen Compton", 12); l += 7 << 16; + shadowminitext(m, l, "HASH, Inc., FormGen, Inc.", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "The 3D Realms Beta Testers", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Nathan Anderson, Wayne Benner", 12); l += 7 << 16; + shadowminitext(m, l, "Glenn Brensinger, Rob Brown", 12); l += 7 << 16; + shadowminitext(m, l, "Erik Harris, Ken Heckbert", 12); l += 7 << 16; + shadowminitext(m, l, "Terry Herrin, Greg Hively", 12); l += 7 << 16; + shadowminitext(m, l, "Hank Leukart, Eric Baker", 12); l += 7 << 16; + shadowminitext(m, l, "Jeff Rausch, Kelly Rogers", 12); l += 7 << 16; + shadowminitext(m, l, "Mike Duncan, Doug Howell", 12); l += 7 << 16; + shadowminitext(m, l, "Bill Blair", 12); l += 7 << 16; + + m = int(origin.X * 65536) + (160 << 16); + l = int(origin.Y * 65536) + (33 << 16); + + shadowminitext(m, l, "Company Product Support", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "The following companies were cool", 12); l += 7 << 16; + shadowminitext(m, l, "enough to give us lots of stuff", 12); l += 7 << 16; + shadowminitext(m, l, "during the making of Duke Nukem 3D.", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Altec Lansing Multimedia", 12); l += 7 << 16; + shadowminitext(m, l, "for tons of speakers and the", 12); l += 7 << 16; + shadowminitext(m, l, "THX-licensed sound system.", 12); l += 7 << 16; + shadowminitext(m, l, "For info call 1-800-548-0620", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Creative Labs, Inc.", 12); l += 7 << 16; + l += 3 << 16; + shadowminitext(m, l, "Thanks for the hardware, guys.", 12); l += 7 << 16; + return true; + } + else if (tilenum == CREDITSTEXT3) + { + Menu_DrawBackground(origin); + mgametextcenter(int(origin.X * 65536), int(origin.Y * 65536) + (50 << 16), "Duke Nukem 3D is a trademark of\n" + "3D Realms Entertainment" + "\n" + "Duke Nukem 3D\n" + "(C) 1996 3D Realms Entertainment"); + + if (VOLUMEONE) + { + mgametextcenter(int(origin.X * 65536), int(origin.Y * 65536) + (106 << 16), "Please read LICENSE.DOC for shareware\n" + "distribution grants and restrictions."); + } + mgametextcenter(int(origin.X * 65536), int(origin.Y * 65536) + ((VOLUMEONE ? 134 : 115) << 16), "Made in Dallas, Texas USA"); + return true; + } + } + return false; +} + + +void GameInterface::DrawCenteredTextScreen(const DVector2 &origin, const char *text, int position, bool bg) +{ + if (bg) Menu_DrawBackground(origin); + else + { + // Only used for the confirmation screen. + int lines = 1; + for (int i = 0; text[i]; i++) if (text[i] == '\n') lines++; + int height = lines * Menu_GetFontHeight(NIT_SmallFont); + position -= height >> 17; + Menu_DrawCursorLeft(160 << 16, 130 << 16, 65536); + } + mgametextcenter(int(origin.X * 65536), int((origin.Y + position) * 65536), text); +} + +void GameInterface::DrawPlayerSprite(const DVector2& origin, bool onteam) +{ + rotatesprite_fs(int(origin.X * 65536) + (260<<16), int(origin.Y*65536) + ((24+(tilesiz[APLAYER].y>>1))<<16), 49152L,0,1441-((((4-((int32_t) totalclock>>4)))&3)*5),0,onteam ? G_GetTeamPalette(playerteam) : G_CheckPlayerColor(playercolor),10); +} + +void GameInterface::QuitToTitle() +{ + g_player[myconnectindex].ps->gm = MODE_DEMO; + if (ud.recstat == 1) + G_CloseDemoWrite(); + artClearMapArt(); +} +END_DUKE_NS + +//---------------------------------------------------------------------------- +// +// Class registration +// +//---------------------------------------------------------------------------- + + +static TMenuClassDescriptor _mm("Duke.MainMenu"); +static TMenuClassDescriptor _lm("Duke.ListMenu"); +static TMenuClassDescriptor _ngcsm("Duke.NewGameCustomSubMenu"); +static TMenuClassDescriptor _ism("Duke.ImageScrollerMenu"); + +void RegisterDukeMenus() +{ + menuClasses.Push(&_mm); + menuClasses.Push(&_lm); + menuClasses.Push(&_ngcsm); + menuClasses.Push(&_ism); +} diff --git a/source/duke3d/src/demo.cpp b/source/duke3d/src/demo.cpp index ea8c1f243..7025715ce 100644 --- a/source/duke3d/src/demo.cpp +++ b/source/duke3d/src/demo.cpp @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "screens.h" #include "i_specialpaths.h" #include "printf.h" +#include "menu/menu.h" BEGIN_DUKE_NS @@ -55,9 +56,9 @@ static int32_t demorec_seeds=1, demo_hasseeds; static void Demo_RestoreModes(int32_t menu) { if (menu) - Menu_Open(myconnectindex); + M_StartControlPanel(false); else - Menu_Close(myconnectindex); + M_ClearMenus(); g_player[myconnectindex].ps->gm &= ~MODE_GAME; g_player[myconnectindex].ps->gm |= MODE_DEMO; @@ -94,8 +95,7 @@ static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine demofnptr = demofn; } - g_demo_recFilePtr = fopenFileReader(demofnptr, g_loadFromGroupOnly); - if (!g_demo_recFilePtr.isOpen()) + if (!g_demo_recFilePtr.OpenFile(demofnptr)) return 0; Bassert(g_whichDemo >= 1); @@ -109,7 +109,7 @@ static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine demo_hasdiffs = saveh.recdiffsp; g_demo_totalCnt = saveh.reccnt; - demo_hasseeds = saveh.synccompress & 2; + demo_hasseeds = 0; i = g_demo_totalCnt/REALGAMETICSPERSEC; OSD_Printf("demo %d duration: %d min %d sec\n", g_whichDemo, i/60, i%60); @@ -142,7 +142,7 @@ void G_OpenDemoWrite(void) if ((g_player[myconnectindex].ps->gm&MODE_GAME) && g_player[myconnectindex].ps->dead_flag) { - Bstrcpy(apStrings[QUOTE_RESERVED4], "CANNOT START DEMO RECORDING WHEN DEAD!"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "CANNOT START DEMO RECORDING WHEN DEAD!"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); ud.recstat = m_recstat = 0; return; @@ -172,14 +172,13 @@ void G_OpenDemoWrite(void) if (g_demo_filePtr == NULL) return; - i=sv_saveandmakesnapshot(*g_demo_filePtr, nullptr, -1, demorec_diffs_cvar, demorec_diffcompress_cvar, - (demorec_seeds_cvar<<1)); + i=sv_saveandmakesnapshot(*g_demo_filePtr, nullptr, -1); if (i) { delete g_demo_filePtr; g_demo_filePtr = nullptr; error_wopen_demo: - Bstrcpy(apStrings[QUOTE_RESERVED4], "FAILED STARTING DEMO RECORDING. SEE CONSOLE FOR DETAILS."); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "FAILED STARTING DEMO RECORDING. SEE CONSOLE FOR DETAILS."); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); ud.recstat = m_recstat = 0; return; @@ -189,7 +188,7 @@ error_wopen_demo: demorec_diffs = demorec_diffs_cvar; demorec_difftics = demorec_difftics_cvar; - Bsprintf(apStrings[QUOTE_RESERVED4], "DEMO %d RECORDING STARTED", demonum-1); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "DEMO %d RECORDING STARTED", demonum-1); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); ud.reccnt = 0; @@ -284,7 +283,7 @@ void G_CloseDemoWrite(void) sv_freemem(); - Bstrcpy(apStrings[QUOTE_RESERVED4], "DEMO RECORDING STOPPED"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "DEMO RECORDING STOPPED"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); } #if KRANDDEBUG @@ -488,7 +487,7 @@ RECHECK: fadepal(0,0,0, 0,252,28); P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1); // JBF 20040308 G_DrawBackground(); - M_DisplayMenus(); + //M_DisplayMenus(); videoNextPage(); fadepal(0,0,0, 252,0,-28); ud.reccnt = 0; @@ -522,7 +521,7 @@ RECHECK: { FX_StopAllSounds(); S_ClearSoundLocks(); - Menu_Open(myconnectindex); + M_StartControlPanel(false); } ready2send = 0; @@ -663,7 +662,7 @@ RECHECK: corrupt: OSD_Printf(OSD_ERROR "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode); nextdemo: - Menu_Open(myconnectindex); + M_StartControlPanel(false); nextdemo_nomenu: foundemo = 0; ud.reccnt = 0; @@ -846,7 +845,7 @@ nextdemo_nomenu: Net_GetPackets(); if (g_player[myconnectindex].gotvote == 0 && voting != -1 && voting != myconnectindex) - gametext_center(60, "Press F1 to Accept, F2 to Decline"); + gametext_center(60, GStrings("TXT_PRESSF1_F2")); } if ((g_player[myconnectindex].ps->gm&MODE_MENU) && (g_player[myconnectindex].ps->gm&MODE_EOL)) @@ -856,16 +855,6 @@ nextdemo_nomenu: goto RECHECK; } - if (I_EscapeTrigger() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && (g_player[myconnectindex].ps->gm&MODE_TYPE) == 0) - { - I_EscapeTriggerClear(); - FX_StopAllSounds(); - S_ClearSoundLocks(); - Menu_Open(myconnectindex); - Menu_Change(MENU_MAIN); - S_MenuSound(); - } - if (Demo_IsProfiling()) { // Do nothing: sampletimer() is reached from M_DisplayMenus() -> @@ -878,15 +867,15 @@ nextdemo_nomenu: if ((g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE) { g_player[myconnectindex].ps->gm = 0; - Menu_Open(myconnectindex); + M_StartControlPanel(false); } } else { - if (ud.recstat != 2) - M_DisplayMenus(); + //if (ud.recstat != 2) + // M_DisplayMenus(); - if ((g_netServer || ud.multimode > 1) && !Menu_IsTextInput(m_currentMenu)) + if ((g_netServer || ud.multimode > 1))// && !Menu_IsTextInput(m_currentMenu)) { ControlInfo noshareinfo; CONTROL_GetInput(&noshareinfo); diff --git a/source/duke3d/src/demo.h b/source/duke3d/src/demo.h index d01128835..f27b0f9dd 100644 --- a/source/duke3d/src/demo.h +++ b/source/duke3d/src/demo.h @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define demo_h_ #include "compat.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" BEGIN_DUKE_NS diff --git a/source/duke3d/src/duke3d.h b/source/duke3d/src/duke3d.h index b8c1c5771..21e187a22 100644 --- a/source/duke3d/src/duke3d.h +++ b/source/duke3d/src/duke3d.h @@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "pragmas.h" #include "polymost.h" #include "gamecvars.h" +#include "menu/menu.h" #define HEAD2 APPNAME @@ -58,7 +59,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define MOVEFIFOSIZ 2 // KEEPINSYNC lunatic/con_lang.lua -#define MAXVOLUMES 7 #define MAXLEVELS 64 #define MAXGAMETYPES 16 @@ -151,9 +151,27 @@ struct GameInterface : ::GameInterface bool validate_hud(int) override; void set_hud_layout(int size) override; void set_hud_scale(int size) override; - bool mouseInactiveConditional(bool condition) override; FString statFPS() override; GameStats getStats() override; + // Access to the front end specific menu code. Use is restricted to the main menu, the ingame menu and the skill/episode selection. + // Everything else is either custom screens or will use the generic option menu style. + void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int orientation) override; + void MenuOpened() override; + void MenuClosed() override; + void MenuSound(EMenuSounds snd) override; + bool CanSave() override; + void CustomMenuSelection(int menu, int item) override; + void StartGame(FGameStartup& gs) override; + FSavegameInfo GetSaveSig() override; + bool DrawSpecialScreen(const DVector2 &origin, int tilenum) override; + void DrawCenteredTextScreen(const DVector2 &origin, const char *text, int position, bool bg) override; + void DrawMenuCaption(const DVector2& origin, const char* text) override; + bool SaveGame(FSaveGameNode*) override; + bool LoadGame(FSaveGameNode*) override; + void DoPrintMessage(int prio, const char*) override; + void DrawPlayerSprite(const DVector2& origin, bool onteam) override; + void QuitToTitle() override; + }; END_DUKE_NS diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index 625dcd27a..644425f06 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -44,8 +44,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gameconfigfile.h" #include "printf.h" #include "m_argv.h" +#include "c_dispatch.h" #include "filesystem/filesystem.h" #include "statistics.h" +#include "menu/menu.h" +#include "mapinfo.h" // Uncomment to prevent anything except mirrors from drawing. It is sensible to // also uncomment ENGINE_CLEAR_SCREEN in build/src/engine_priv.h. @@ -76,7 +79,7 @@ int32_t g_quitDeadline = 0; int32_t g_cameraDistance = 0, g_cameraClock = 0; static int32_t g_quickExit; -char boardfilename[BMAX_PATH] = {0}, currentboardfilename[BMAX_PATH] = {0}; +char boardfilename[BMAX_PATH]; int32_t voting = -1; int32_t vote_map = -1, vote_episode = -1; @@ -112,14 +115,14 @@ const char *G_DefaultRtsFile(void) return defaultrtsfilename[GAME_WW2GI]; else if (NAPALM) { - if (!testkopen(defaultrtsfilename[GAME_NAPALM],0) && testkopen(defaultrtsfilename[GAME_NAM],0)) + if (!fileSystem.FileExists(defaultrtsfilename[GAME_NAPALM]) && fileSystem.FileExists(defaultrtsfilename[GAME_NAM])) return defaultrtsfilename[GAME_NAM]; // NAM/NAPALM Sharing else return defaultrtsfilename[GAME_NAPALM]; } else if (NAM) { - if (!testkopen(defaultrtsfilename[GAME_NAM],0) && testkopen(defaultrtsfilename[GAME_NAPALM],0)) + if (!fileSystem.FileExists(defaultrtsfilename[GAME_NAM]) && fileSystem.FileExists(defaultrtsfilename[GAME_NAPALM])) return defaultrtsfilename[GAME_NAPALM]; // NAM/NAPALM Sharing else return defaultrtsfilename[GAME_NAM]; @@ -204,13 +207,6 @@ void G_HandleSpecialKeys(void) G_UpdateScreenArea(); } - if (inputState.UnboundKeyPressed(sc_F12)) - { - inputState.ClearKeyStatus(sc_F12); - videoCaptureScreen(); - P_DoQuote(QUOTE_SCREEN_SAVED, &myplayer); - } - // only dispatch commands here when not in a game if ((myplayer.gm & MODE_GAME) != MODE_GAME) OSD_DispatchQueued(); @@ -4416,11 +4412,6 @@ extern int G_StartRTS(int lumpNum, int localPlayer) return 0; } -void G_PrintCurrentMusic(void) -{ - Bsnprintf(apStrings[QUOTE_MUSIC], MAXQUOTELEN, "Playing %s", g_mapInfo[g_musicIndex].musicfn); - P_DoQuote(QUOTE_MUSIC, g_player[myconnectindex].ps); -} // Trying to sanitize the mess of options and the mess of variables the mess was stored in. (Did I say this was a total mess before...? >) ) // Hopefully this is more comprehensible, at least it neatly stores everything useful in a single linear value... @@ -4485,7 +4476,7 @@ void G_HandleLocalKeys(void) { if (inputState.UnboundKeyPressed(sc_F1) || inputState.UnboundKeyPressed(sc_F2) || cl_autovote) { - G_AddUserQuote("Vote Cast"); + G_AddUserQuote(GStrings("VoteCast")); Net_SendMapVote(inputState.UnboundKeyPressed(sc_F1) || cl_autovote ? cl_autovote-1 : 0); inputState.ClearKeyStatus(sc_F1); inputState.ClearKeyStatus(sc_F2); @@ -4667,25 +4658,6 @@ void G_HandleLocalKeys(void) { if (SHIFTS_IS_PRESSED) { - if (ridiculeNum == 5 && myplayer.fta > 0 && myplayer.ftq == QUOTE_MUSIC) - { - const unsigned int maxi = VOLUMEALL ? MUS_FIRST_SPECIAL : 6; - - unsigned int const oldMusicIndex = g_musicIndex; - unsigned int MyMusicIndex = g_musicIndex; - do - { - ++MyMusicIndex; - if (MyMusicIndex >= maxi) - MyMusicIndex = 0; - } - while (S_TryPlayLevelMusic(MyMusicIndex) && MyMusicIndex != oldMusicIndex); - - G_PrintCurrentMusic(); - - return; - } - G_AddUserQuote(*CombatMacros[ridiculeNum-1]); Net_SendTaunt(ridiculeNum); @@ -4717,136 +4689,6 @@ void G_HandleLocalKeys(void) typebuf[0] = 0; } - if (inputState.UnboundKeyPressed(sc_F1) && !(G_GetLogoFlags() & LOGO_NOHELP)/* || (ud.show_help && I_AdvanceTrigger())*/) - { - inputState.ClearKeyStatus(sc_F1); - - Menu_Change(MENU_STORY); - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2)) - { - ready2send = 0; - totalclock = ototalclock; - screenpeek = myconnectindex; - } - } - - // if((!net_server && ud.multimode < 2)) - { - if (ud.recstat != 2 && inputState.UnboundKeyPressed(sc_F2)) - { - inputState.ClearKeyStatus(sc_F2); - -FAKE_F2: - if (sprite[myplayer.i].extra <= 0) - { - P_DoQuote(QUOTE_SAVE_DEAD, &myplayer); - return; - } - - Menu_Change(MENU_SAVE); - - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2)) - { - ready2send = 0; - totalclock = ototalclock; - screenpeek = myconnectindex; - } - } - - if (inputState.UnboundKeyPressed(sc_F3)) - { - inputState.ClearKeyStatus(sc_F3); - -FAKE_F3: - Menu_Change(MENU_LOAD); - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 0; - totalclock = ototalclock; - } - - screenpeek = myconnectindex; - } - } - - if (inputState.GetKeyStatus(sc_F4)) - if (inputState.UnboundKeyPressed(sc_F4)) - { - inputState.ClearKeyStatus(sc_F4); - - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 0; - totalclock = ototalclock; - } - - Menu_Change(MENU_SOUND_INGAME); - } - - if (inputState.UnboundKeyPressed(sc_F5) && MusicEnabled()) - { - map_t *const pMapInfo = &g_mapInfo[g_musicIndex]; - char *const musicString = apStrings[QUOTE_MUSIC]; - - inputState.ClearKeyStatus(sc_F5); - - if (pMapInfo->musicfn != NULL) - Bsnprintf(musicString, MAXQUOTELEN, "%s. Use SHIFT-F5 to change.", pMapInfo->musicfn); - else - musicString[0] = '\0'; - - P_DoQuote(QUOTE_MUSIC, g_player[myconnectindex].ps); - } - - if ((buttonMap.ButtonDown(gamefunc_Quick_Save) || g_doQuickSave == 1) && (myplayer.gm & MODE_GAME)) - { - buttonMap.ClearButton(gamefunc_Quick_Save); - - g_doQuickSave = 0; - - if (!g_lastusersave.isValid()) - goto FAKE_F2; - - inputState.keyFlushChars(); - - if (sprite[myplayer.i].extra <= 0) - { - P_DoQuote(QUOTE_SAVE_DEAD, &myplayer); - return; - } - - g_screenCapture = 1; - G_DrawRooms(myconnectindex,65536); - g_screenCapture = 0; - - if (g_lastusersave.isValid()) - { - savebrief_t & sv = g_lastusersave; - - // dirty hack... char 127 in last position indicates an auto-filled name - if (sv.name[MAXSAVEGAMENAME] == 127) - { - strncpy(sv.name, g_mapInfo[ud.volume_number * MAXLEVELS + ud.level_number].name, MAXSAVEGAMENAME); - sv.name[MAXSAVEGAMENAME] = 127; - } - - g_quickload = &sv; - G_SavePlayerMaybeMulti(sv); - } - } - if (buttonMap.ButtonDown(gamefunc_Third_Person_View)) { buttonMap.ClearButton(gamefunc_Third_Person_View); @@ -4859,63 +4701,6 @@ FAKE_F3: P_DoQuote(QUOTE_VIEW_MODE_OFF + myplayer.over_shoulder_on, &myplayer); } - if (inputState.UnboundKeyPressed(sc_F8)) - { - inputState.ClearKeyStatus(sc_F8); - - int const fta = !hud_messages; - hud_messages = 1; - P_DoQuote(fta ? QUOTE_MESSAGES_ON : QUOTE_MESSAGES_OFF, &myplayer); - hud_messages = fta; - } - - if ((buttonMap.ButtonDown(gamefunc_Quick_Load) || g_doQuickSave == 2) && (myplayer.gm & MODE_GAME)) - { - buttonMap.ClearButton(gamefunc_Quick_Load); - - g_doQuickSave = 0; - - if (g_quickload == nullptr || !g_quickload->isValid()) - goto FAKE_F3; - else if (g_quickload->isValid()) - { - inputState.keyFlushChars(); - inputState.ClearKeysDown(); - S_PauseSounds(true); - if (G_LoadPlayerMaybeMulti(*g_quickload) != 0) - g_quickload->reset(); - } - } - - if (inputState.UnboundKeyPressed(sc_F10)) - { - inputState.ClearKeyStatus(sc_F10); - - Menu_Change(MENU_QUIT_INGAME); - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 0; - totalclock = ototalclock; - } - } - - if (inputState.UnboundKeyPressed(sc_F11)) - { - inputState.ClearKeyStatus(sc_F11); - - Menu_Change(MENU_COLCORR_INGAME); - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 0; - totalclock = ototalclock; - } - } if (ud.overhead_on != 0) { @@ -4941,13 +4726,6 @@ FAKE_F3: G_UpdateScreenArea(); } - if (buttonMap.ButtonDown(gamefunc_AutoRun)) - { - buttonMap.ClearButton(gamefunc_AutoRun); - cl_autorun= 1-cl_autorun; - P_DoQuote(QUOTE_RUN_MODE_OFF + cl_autorun, &myplayer); - } - if (buttonMap.ButtonDown(gamefunc_Map)) { buttonMap.ClearButton(gamefunc_Map); @@ -4963,17 +4741,6 @@ FAKE_F3: ud.last_overhead = ud.overhead_on; } -#ifdef __ANDROID__ - if (ud.overhead_on == 1) - ud.scrollmode = 0; - else if (ud.overhead_on == 2) - { - ud.scrollmode = 1; - ud.folx = g_player[screenpeek].ps->opos.x; - ud.foly = g_player[screenpeek].ps->opos.y; - ud.fola = g_player[screenpeek].ps->oang; - } -#endif g_restorePalette = 1; G_UpdateScreenArea(); } @@ -5048,7 +4815,8 @@ static int32_t S_DefineMusic(const char *ID, const char *name) return -1; } - return S_DefineAudioIfSupported(&g_mapInfo[sel].musicfn, name); + mapList[sel].music = name; + return 0; } static int parsedefinitions_game(scriptfile *, int); @@ -5299,7 +5067,7 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) break; } - if (fileName == NULL || check_file_exist(fileName)) + if (fileName == NULL || fileSystem.FileExists(fileName)) break; if (S_DefineMusic(musicID, fileName) == -1) @@ -5447,7 +5215,7 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) break; } - if (fileName == NULL || check_file_exist(fileName)) + if (fileName == NULL || fileSystem.FileExists(fileName)) break; // maybe I should have just packed this into a sound_t and passed a reference... @@ -5617,25 +5385,15 @@ static void G_FreeHashAnim(const char * /*string*/, intptr_t key) static void G_Cleanup(void) { - ReadSaveGameHeaders(); // for culling + //ReadSaveGameHeaders(); // for culling int32_t i; for (i=(MAXLEVELS*(MAXVOLUMES+1))-1; i>=0; i--) // +1 volume for "intro", "briefing" music { - Xfree(g_mapInfo[i].name); - Xfree(g_mapInfo[i].filename); - Xfree(g_mapInfo[i].musicfn); - G_FreeMapState(i); } - for (i=MAXQUOTES-1; i>=0; i--) - { - Xfree(apStrings[i]); - Xfree(apXStrings[i]); - } - for (i=MAXPLAYERS-1; i>=0; i--) { Xfree(g_player[i].ps); @@ -5676,7 +5434,6 @@ static void G_Cleanup(void) void G_Shutdown(void) { S_SoundShutdown(); - S_MusicShutdown(); CONTROL_Shutdown(); engineUnInit(); G_Cleanup(); @@ -5901,49 +5658,35 @@ static void G_Startup(void) if (userConfig.CommandMap.IsNotEmpty()) { + FString startupMap; if (VOLUMEONE) { initprintf("The -map option is available in the registered version only!\n"); - boardfilename[0] = 0; } else { - char *dot, *slash; + startupMap = userConfig.CommandMap; + if (startupMap.IndexOfAny("/\\") < 0) startupMap.Insert(0, "/"); + DefaultExtension(startupMap, ".map"); + startupMap.Substitute("\\", "/"); + NormalizeFileName(startupMap); - boardfilename[0] = '/'; - boardfilename[1] = 0; - Bstrcat(boardfilename, userConfig.CommandMap); - - dot = Bstrrchr(boardfilename,'.'); - slash = Bstrrchr(boardfilename,'/'); - if (!slash) slash = Bstrrchr(boardfilename,'\\'); - - if ((!slash && !dot) || (slash && dot < slash)) - Bstrcat(boardfilename,".map"); - - Bcorrectfilename(boardfilename,0); - - if (testkopen(boardfilename, 0)) + if (fileSystem.FileExists(startupMap)) { - initprintf("Using level: \"%s\".\n",boardfilename); + initprintf("Using level: \"%s\".\n",startupMap.GetChars()); } else { - initprintf("Level \"%s\" not found.\n",boardfilename); + initprintf("Level \"%s\" not found.\n",startupMap.GetChars()); boardfilename[0] = 0; } } + strncpy(boardfilename, startupMap, BMAX_PATH); } for (i=0; i 1) @@ -5952,8 +5695,6 @@ static void G_Startup(void) if (TileFiles.artLoadFiles("tiles%03i.art") < 0) G_GameExit("Failed loading art."); - cacheAllSounds(); - // Make the fullscreen nuke logo background non-fullbright. Has to be // after dynamic tile remapping (from C_Compile) and loading tiles. picanm[LOADSCREEN].sf |= PICANM_NOFULLBRIGHT_BIT; @@ -5968,7 +5709,7 @@ static void P_SetupMiscInputSettings(void) { auto ps = g_player[myconnectindex].ps; - ps->aim_mode = in_aimmode; + ps->aim_mode = in_mousemode; ps->auto_aim = cl_autoaim; ps->weaponswitch = cl_weaponswitch; } @@ -5991,7 +5732,7 @@ void G_UpdatePlayerFromMenu(void) /*int32_t j = p.team;*/ P_SetupMiscInputSettings(); - p.palookup = g_player[myconnectindex].pcolor = playercolor; + p.palookup = g_player[myconnectindex].pcolor = G_CheckPlayerColor(playercolor); g_player[myconnectindex].pteam = playerteam; @@ -6006,8 +5747,8 @@ void G_BackToMenu(void) if (ud.recstat == 1) G_CloseDemoWrite(); ud.warp_on = 0; g_player[myconnectindex].ps->gm = 0; - Menu_Open(myconnectindex); - Menu_Change(MENU_MAIN); + M_StartControlPanel(false); + M_SetMenu(NAME_MainMenu); inputState.keyFlushChars(); } @@ -6015,7 +5756,8 @@ static int G_EndOfLevel(void) { auto &p = *g_player[myconnectindex].ps; - STAT_Update(ud.eog); + if ((currentLevel->flags & MI_FORCEEOG)) ud.eog = 1; // if the finished level says to end the game, end it! + STAT_Update(ud.eog); P_SetGamePalette(&p, BASEPAL, 0); P_UpdateScreenPal(&p); @@ -6040,7 +5782,7 @@ static int G_EndOfLevel(void) // Clear potentially loaded per-map ART only after the bonus screens. artClearMapArt(); - if (ud.eog || G_HaveUserMap()) + if (ud.eog || G_HaveUserMap() || (currentLevel->flags & MI_FORCEEOG)) { ud.eog = 0; if ((!g_netServer && ud.multimode < 2)) @@ -6050,9 +5792,7 @@ static int G_EndOfLevel(void) G_DoOrderScreen(); #endif p.gm = 0; - Menu_Open(myconnectindex); - Menu_Change(MENU_MAIN); - return 2; + return 2; } else { @@ -6122,7 +5862,7 @@ int GameInterface::app_main() g_Shareware = 1; else { - if (testkopen("DUKESW.BIN", 1)) // JBF 20030810 + if (fileSystem.FileExists("DUKESW.BIN")) // JBF 20030810 { g_Shareware = 1; } @@ -6178,7 +5918,7 @@ int GameInterface::app_main() for (int i=1, j=numplayers; jteam = g_player[j].pteam = i; g_player[j].ps->weaponswitch = 3; g_player[j].ps->auto_aim = 0; @@ -6198,6 +5938,8 @@ int GameInterface::app_main() userConfig.AddDefs.reset(); + cacheAllSounds(); + if (enginePostInit()) G_FatalEngineError(); @@ -6249,8 +5991,6 @@ int GameInterface::app_main() system_getcvars(); - if (quitevent) return 4; - if (g_networkMode != NET_DEDICATED_SERVER && validmodecnt > 0) { if (videoSetGameMode(ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP, 1) < 0) @@ -6294,7 +6034,6 @@ int GameInterface::app_main() videoSetPalette(0, myplayer.palette, 0); S_SoundStartup(); - S_MusicStartup(); } // check if the minifont will support lowercase letters (3136-3161) @@ -6309,8 +6048,6 @@ int GameInterface::app_main() Menu_Init(); } - ReadSaveGameHeaders(); - FX_StopAllSounds(); S_ClearSoundLocks(); @@ -6335,8 +6072,6 @@ MAIN_LOOP_RESTART: for (int32_t & q : user_quote_time) q = 0; - Menu_Change(MENU_MAIN); - if(g_netClient) { OSD_Printf("Waiting for initial snapshot..."); @@ -6380,6 +6115,9 @@ MAIN_LOOP_RESTART: if (g_networkMode != NET_DEDICATED_SERVER) { + M_StartControlPanel(false); + M_SetMenu(NAME_MainMenu); + if (G_PlaybackDemo()) { FX_StopAllSounds(); @@ -6390,6 +6128,7 @@ MAIN_LOOP_RESTART: } else G_UpdateScreenArea(); + // G_GameExit(" "); /// ud.showweapons = ud.config.ShowWeapons; @@ -6400,7 +6139,7 @@ MAIN_LOOP_RESTART: myplayer.palookup = g_player[myconnectindex].pcolor = G_GetTeamPalette(g_player[myconnectindex].pteam); else { - if (playercolor) myplayer.palookup = g_player[myconnectindex].pcolor = playercolor; + if (playercolor) myplayer.palookup = g_player[myconnectindex].pcolor = G_CheckPlayerColor(playercolor); else myplayer.palookup = g_player[myconnectindex].pcolor; } @@ -6414,11 +6153,12 @@ MAIN_LOOP_RESTART: do //main loop { - if (gameHandleEvents() && quitevent) - { - inputState.SetKeyStatus(sc_Escape, 1); - quitevent = 0; - } + gameHandleEvents(); + if (myplayer.gm == MODE_DEMO) + { + M_ClearMenus(); + goto MAIN_LOOP_RESTART; + } // only allow binds to function if the player is actually in a game (not in a menu, typing, et cetera) or demo inputState.SetBindsEnabled(!!(myplayer.gm & (MODE_GAME|MODE_DEMO))); @@ -6523,12 +6263,7 @@ MAIN_LOOP_RESTART: inputState.keyFlushChars(); videoNextPage(); - g_screenCapture = 1; - G_DrawRooms(myconnectindex, 65536); - g_screenCapture = 0; - - G_SavePlayerMaybeMulti(g_lastautosave, true); - g_quickload = &g_lastautosave; + M_Autosave(); g_saveRequested = false; } @@ -6600,7 +6335,7 @@ int G_DoMoveThings(void) { if (ldist(&sprite[pPlayer->i], &sprite[hitData.sprite]) < 9216) { - Bsprintf(apStrings[QUOTE_RESERVED3], "%s", &g_player[playerNum].user_name[0]); + quoteMgr.InitializeQuote(QUOTE_RESERVED3, "%s", &g_player[playerNum].user_name[0]); pPlayer->fta = 12, pPlayer->ftq = QUOTE_RESERVED3; } } diff --git a/source/duke3d/src/game.h b/source/duke3d/src/game.h index cf89ab514..4b77984cf 100644 --- a/source/duke3d/src/game.h +++ b/source/duke3d/src/game.h @@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gamevars.h" #include "mmulti.h" #include "network.h" +#include "menu/menu.h" BEGIN_DUKE_NS @@ -118,32 +119,12 @@ void A_DeleteSprite(int spriteNum); static inline int32_t G_GetLogoFlags(void) { -#if !defined LUNATIC return Gv_GetVarByLabel("LOGO_FLAGS",255, -1, -1); -#else - extern int32_t g_logoFlags; - return g_logoFlags; -#endif } -#ifdef LUNATIC -typedef struct { - vec3_t pos; - int32_t dist, clock; - fix16_t q16horiz, q16ang; - int16_t sect; -} camera_t; - -extern camera_t g_camera; - -# define CAMERA(Membname) (g_camera.Membname) -# define CAMERADIST (g_camera.dist) -# define CAMERACLOCK (g_camera.clock) -#else # define CAMERA(Membname) (ud.camera ## Membname) # define CAMERADIST g_cameraDistance # define CAMERACLOCK g_cameraClock -#endif #endif @@ -155,9 +136,7 @@ extern camera_t g_camera; #define MAX_RETURN_VALUES 6 typedef struct { -#if !defined LUNATIC vec3_t camerapos; -#endif int32_t const_visibility,uw_framerate; int32_t camera_time,folfvel,folavel,folx,foly,fola; int32_t reccnt; @@ -182,16 +161,12 @@ typedef struct { int32_t playerbest; - int32_t default_volume, default_skill; - int32_t returnvar[MAX_RETURN_VALUES-1]; uint32_t userbytever; -#if !defined LUNATIC fix16_t cameraq16ang, cameraq16horiz; int16_t camerasect; -#endif int16_t pause_on,from_bonus; int16_t camerasprite,last_camsprite; int16_t last_level,secretlevel; @@ -224,7 +199,7 @@ extern user_defs ud; // this is checked against http://eduke32.com/VERSION extern const char *s_buildDate; -extern char boardfilename[BMAX_PATH], currentboardfilename[BMAX_PATH]; +extern char boardfilename[BMAX_PATH]; #define USERMAPMUSICFAKEVOLUME MAXVOLUMES #define USERMAPMUSICFAKELEVEL (MAXLEVELS-1) #define USERMAPMUSICFAKESLOT ((USERMAPMUSICFAKEVOLUME * MAXLEVELS) + USERMAPMUSICFAKELEVEL) @@ -506,11 +481,6 @@ static inline int G_GetViewscreenSizeShift(uspriteptr_t const spr) #endif } -extern void G_PrintCurrentMusic(void); - -#ifdef LUNATIC -void El_SetCON(const char *conluacode); -#endif EXTERN_INLINE_HEADER void G_SetStatusBarScale(int32_t sc); diff --git a/source/duke3d/src/gamedef.cpp b/source/duke3d/src/gamedef.cpp index c4093393d..1f2718dff 100644 --- a/source/duke3d/src/gamedef.cpp +++ b/source/duke3d/src/gamedef.cpp @@ -36,11 +36,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "savegame.h" #include "printf.h" #include "m_argv.h" +#include "menu/menu.h" +#include "stringtable.h" +#include "mapinfo.h" + +void C_CON_SetButtonAlias(int num, const char* text); +void C_CON_ClearButtonAlias(int num); BEGIN_DUKE_NS #define LINE_NUMBER (g_lineNumber << 12) + int32_t g_scriptVersion = 13; // 13 = 1.3D-style CON files, 14 = 1.4/1.5 style CON files char g_scriptFileName[BMAX_PATH] = "(none)"; // file we're currently compiling @@ -1902,7 +1909,7 @@ static int C_CountCaseStatements() static void C_Include(const char *confile) { - auto fp = kopenFileReader(confile,0); + auto fp = fileSystem.OpenFileReader(confile,0); if (!fp.isOpen()) { @@ -2023,17 +2030,14 @@ void C_DefineMusic(int volumeNum, int levelNum, const char *fileName) if (strcmp(fileName, "/.") == 0) return; - map_t *const pMapInfo = &g_mapInfo[(MAXLEVELS*volumeNum)+levelNum]; - - Xfree(pMapInfo->musicfn); - pMapInfo->musicfn = dup_filename(fileName); + mapList[(MAXLEVELS * volumeNum) + levelNum].music = fileName; } void C_DefineVolumeFlags(int32_t vol, int32_t flags) { Bassert((unsigned)vol < MAXVOLUMES); - g_volumeFlags[vol] = flags; + gVolumeFlags[vol] = flags; } void C_UndefineVolume(int32_t vol) @@ -2043,12 +2047,12 @@ void C_UndefineVolume(int32_t vol) for (bssize_t i = 0; i < MAXLEVELS; i++) C_UndefineLevel(vol, i); - g_volumeNames[vol][0] = '\0'; + gVolumeNames[vol] = ""; g_volumeCnt = 0; for (bssize_t i = MAXVOLUMES-1; i >= 0; i--) { - if (g_volumeNames[i][0]) + if (gVolumeNames[i].IsNotEmpty()) { g_volumeCnt = i+1; break; @@ -2060,12 +2064,12 @@ void C_UndefineSkill(int32_t skill) { Bassert((unsigned)skill < MAXSKILLS); - g_skillNames[skill][0] = '\0'; + gSkillNames[skill] = ""; g_skillCnt = 0; for (bssize_t i = MAXSKILLS-1; i >= 0; i--) { - if (g_skillNames[i][0]) + if (gSkillNames[i][0]) { g_skillCnt = i+1; break; @@ -2078,12 +2082,12 @@ void C_UndefineLevel(int32_t vol, int32_t lev) Bassert((unsigned)vol < MAXVOLUMES); Bassert((unsigned)lev < MAXLEVELS); - map_t *const map = &g_mapInfo[(MAXLEVELS*vol)+lev]; + auto& gmap = mapList[(MAXLEVELS * vol) + lev]; - DO_FREE_AND_NULL(map->filename); - DO_FREE_AND_NULL(map->name); - map->partime = 0; - map->designertime = 0; + gmap.fileName = ""; + gmap.name = ""; + gmap.parTime = 0; + gmap.designerTime = 0; } LUNATIC_EXTERN int32_t C_SetDefName(const char *name) @@ -2160,126 +2164,33 @@ LUNATIC_EXTERN void C_DefineProjectile(int32_t j, int32_t what, int32_t val) int32_t C_AllocQuote(int32_t qnum) { Bassert((unsigned)qnum < MAXQUOTES); - - if (apStrings[qnum] == NULL) - { - apStrings[qnum] = (char *)Xcalloc(MAXQUOTELEN,sizeof(uint8_t)); - return 1; - } - - return 0; + // No longer needed, quotes are now FStrings. + return 1; } -#ifndef EDUKE32_TOUCH_DEVICES -static void C_ReplaceQuoteSubstring(const size_t q, char const * const query, char const * const replacement) -{ - size_t querylength = Bstrlen(query); - - for (bssize_t i = MAXQUOTELEN - querylength - 2; i >= 0; i--) - if (Bstrncmp(&apStrings[q][i], query, querylength) == 0) - { - Bmemset(tempbuf, 0, sizeof(tempbuf)); - Bstrncpy(tempbuf, apStrings[q], i); - Bstrcat(tempbuf, replacement); - Bstrcat(tempbuf, &apStrings[q][i + querylength]); - Bstrncpy(apStrings[q], tempbuf, MAXQUOTELEN - 1); - i = MAXQUOTELEN - querylength - 2; - } -} -#endif - void C_InitQuotes(void) { - for (int i = 0; i < 128; i++) C_AllocQuote(i); - -#ifdef EDUKE32_TOUCH_DEVICES - apStrings[QUOTE_DEAD] = 0; -#else - // WTF ?!? - char const * const OpenGameFunc = buttonMap.GetButtonName(gamefunc_Open); - C_ReplaceQuoteSubstring(QUOTE_DEAD, "SPACE", OpenGameFunc); - C_ReplaceQuoteSubstring(QUOTE_DEAD, "OPEN", OpenGameFunc); - C_ReplaceQuoteSubstring(QUOTE_DEAD, "USE", OpenGameFunc); +#if 0 + auto openkeys = Bindings.GetKeysForCommand("+open"); + if (openkeys.Size()) + { + auto OpenGameFunc = C_NameKeys(openkeys.Data(), 1); + quoteMgr.Substitute(QUOTE_DEAD, "SPACE", OpenGameFunc); + quoteMgr.Substitute(QUOTE_DEAD, "OPEN", OpenGameFunc); + quoteMgr.Substitute(QUOTE_DEAD, "USE", OpenGameFunc); + } #endif - // most of these are based on Blood, obviously - const char *PlayerObituaries[] = - { - "^02%s^02 beat %s^02 like a cur", - "^02%s^02 broke %s", - "^02%s^02 body bagged %s", - "^02%s^02 boned %s^02 like a fish", - "^02%s^02 castrated %s", - "^02%s^02 creamed %s", - "^02%s^02 crushed %s", - "^02%s^02 destroyed %s", - "^02%s^02 diced %s", - "^02%s^02 disemboweled %s", - "^02%s^02 erased %s", - "^02%s^02 eviscerated %s", - "^02%s^02 flailed %s", - "^02%s^02 flattened %s", - "^02%s^02 gave AnAl MaDnEsS to %s", - "^02%s^02 gave %s^02 Anal Justice", - "^02%s^02 hosed %s", - "^02%s^02 hurt %s^02 real bad", - "^02%s^02 killed %s", - "^02%s^02 made dog meat out of %s", - "^02%s^02 made mincemeat out of %s", - "^02%s^02 manhandled %s", - "^02%s^02 massacred %s", - "^02%s^02 mutilated %s", - "^02%s^02 murdered %s", - "^02%s^02 neutered %s", - "^02%s^02 punted %s", - "^02%s^02 reamed %s", - "^02%s^02 ripped %s^02 a new orifice", - "^02%s^02 rocked %s", - "^02%s^02 sent %s^02 to hell", - "^02%s^02 shredded %s", - "^02%s^02 slashed %s", - "^02%s^02 slaughtered %s", - "^02%s^02 sliced %s", - "^02%s^02 smacked %s around", - "^02%s^02 smashed %s", - "^02%s^02 snuffed %s", - "^02%s^02 sodomized %s", - "^02%s^02 splattered %s", - "^02%s^02 sprayed %s", - "^02%s^02 squashed %s", - "^02%s^02 throttled %s", - "^02%s^02 toasted %s", - "^02%s^02 vented %s", - "^02%s^02 ventilated %s", - "^02%s^02 wasted %s", - "^02%s^02 wrecked %s", - }; - - const char *PlayerSelfObituaries[] = - { - "^02%s^02 is excrement", - "^02%s^02 is hamburger", - "^02%s^02 suffered scrotum separation", - "^02%s^02 volunteered for population control", - "^02%s^02 has suicided", - "^02%s^02 bled out", - }; - - EDUKE32_STATIC_ASSERT(OBITQUOTEINDEX + ARRAY_SIZE(PlayerObituaries)-1 < MAXQUOTES); - EDUKE32_STATIC_ASSERT(SUICIDEQUOTEINDEX + ARRAY_SIZE(PlayerSelfObituaries)-1 < MAXQUOTES); - - g_numObituaries = ARRAY_SIZE(PlayerObituaries); + g_numObituaries = 48; for (bssize_t i = g_numObituaries - 1; i >= 0; i--) { - if (C_AllocQuote(i + OBITQUOTEINDEX)) - Bstrcpy(apStrings[i + OBITQUOTEINDEX], PlayerObituaries[i]); + quoteMgr.FormatQuote(i + OBITQUOTEINDEX, "$TXT_OBITUARY%d", i + 1); } - g_numSelfObituaries = ARRAY_SIZE(PlayerSelfObituaries); + g_numSelfObituaries = 6; for (bssize_t i = g_numSelfObituaries - 1; i >= 0; i--) { - if (C_AllocQuote(i + SUICIDEQUOTEINDEX)) - Bstrcpy(apStrings[i + SUICIDEQUOTEINDEX], PlayerSelfObituaries[i]); + quoteMgr.FormatQuote(i + SUICIDEQUOTEINDEX, "$TXT_SELFOBIT%d", i + 1); } } @@ -3158,7 +3069,7 @@ DO_DEFSTATE: case CON_QUOTE: C_GetNextValue(LABEL_DEFINE); - if (EDUKE32_PREDICT_FALSE(((unsigned)g_scriptPtr[-1] >= MAXQUOTES) || apStrings[g_scriptPtr[-1]] == NULL)) + if (EDUKE32_PREDICT_FALSE(((unsigned)g_scriptPtr[-1] >= MAXQUOTES))) { g_errorCnt++; C_ReportError(-1); @@ -3558,19 +3469,7 @@ DO_DEFSTATE: initprintf("%s:%d: warning: duplicate dynamicremap statement\n",g_scriptFileName,g_lineNumber); g_warningCnt++; } -#ifdef DYNTILEREMAP_ENABLE -#ifdef DEBUGGINGAIDS - else - initprintf("Using dynamic tile remapping\n"); -#endif g_dynamicTileMapping = 1; -#else - else - { - initprintf("%s:%d: warning: dynamic tile remapping is disabled in this build\n",g_scriptFileName,g_lineNumber); - g_warningCnt++; - } -#endif continue; case CON_DYNAMICSOUNDREMAP: @@ -5015,23 +4914,11 @@ repeatcase: continue; } - i = 0; - - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - g_volumeNames[j][i] = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= (signed)sizeof(g_volumeNames[j])-1)) - { - initprintf("%s:%d: warning: truncating volume name to %d characters.\n", - g_scriptFileName,g_lineNumber,(int32_t)sizeof(g_volumeNames[j])-1); - g_warningCnt++; - scriptSkipLine(); - break; - } - } + i = strcspn(textptr, "\r\n"); + gVolumeNames[j] = FStringTable::MakeMacro(textptr, i); + textptr += i; + g_volumeCnt = j+1; - g_volumeNames[j][i] = '\0'; continue; case CON_DEFINEVOLUMEFLAGS: @@ -5088,7 +4975,7 @@ repeatcase: } } build.Push(0); - buttonMap.SetButtonAlias(j, build.Data()); + C_CON_SetButtonAlias(j, build.Data()); } continue; @@ -5107,7 +4994,7 @@ repeatcase: continue; } - buttonMap.ClearButtonAlias(j); + C_CON_ClearButtonAlias(j); continue; case CON_DEFINESKILLNAME: @@ -5128,27 +5015,14 @@ repeatcase: continue; } - i = 0; - - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - g_skillNames[j][i] = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= (signed)sizeof(g_skillNames[j])-1)) - { - initprintf("%s:%d: warning: truncating skill name to %d characters.\n", - g_scriptFileName,g_lineNumber,(int32_t)sizeof(g_skillNames[j])-1); - g_warningCnt++; - scriptSkipLine(); - break; - } - } - - g_skillNames[j][i] = '\0'; + i = strcspn(textptr, "\r\n"); + gSkillNames[j] = FStringTable::MakeMacro(textptr, i); + textptr+=i; for (i=0; i sizeof(g_mapInfo[j*MAXLEVELS+k].filename)) - g_mapInfo[j *MAXLEVELS+k].filename = (char *)Xrealloc(g_mapInfo[j*MAXLEVELS+k].filename,(Bstrlen(tempbuf)+1)); - - Bstrcpy(g_mapInfo[j*MAXLEVELS+k].filename,tempbuf); + mapList[j * MAXLEVELS + k].SetFileName(tempbuf); C_SkipComments(); - g_mapInfo[j *MAXLEVELS+k].partime = - (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*REALGAMETICSPERSEC*60)+ - (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))*REALGAMETICSPERSEC); + mapList[j *MAXLEVELS+k].parTime = + (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*60)+ + (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))); textptr += 5; scriptSkipSpaces(); @@ -5317,9 +5186,9 @@ repeatcase: // cheap hack, 0.99 doesn't have the 3D Realms time if (*(textptr+2) == ':') { - g_mapInfo[j *MAXLEVELS+k].designertime = - (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*REALGAMETICSPERSEC*60)+ - (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))*REALGAMETICSPERSEC); + mapList[j *MAXLEVELS+k].designerTime = + (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*60)+ + (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))); textptr += 5; scriptSkipSpaces(); @@ -5344,19 +5213,13 @@ repeatcase: tempbuf[i] = '\0'; - if (g_mapInfo[j*MAXLEVELS+k].name == NULL) - g_mapInfo[j*MAXLEVELS+k].name = (char *)Xcalloc(Bstrlen(tempbuf)+1,sizeof(uint8_t)); - else if ((Bstrlen(tempbuf)+1) > sizeof(g_mapInfo[j*MAXLEVELS+k].name)) - g_mapInfo[j *MAXLEVELS+k].name = (char *)Xrealloc(g_mapInfo[j*MAXLEVELS+k].name,(Bstrlen(tempbuf)+1)); - - /* initprintf("level name string len: %d\n",Bstrlen(tempbuf)); */ - - Bstrcpy(g_mapInfo[j*MAXLEVELS+k].name,tempbuf); + mapList[j * MAXLEVELS + k].SetName(tempbuf); continue; case CON_DEFINEQUOTE: case CON_REDEFINEQUOTE: + { if (tw == CON_DEFINEQUOTE) { g_scriptPtr--; @@ -5381,53 +5244,27 @@ repeatcase: if (tw == CON_DEFINEQUOTE) g_scriptPtr--; - i = 0; - scriptSkipSpaces(); - if (tw == CON_REDEFINEQUOTE) - { - if (apXStrings[g_numXStrings] == NULL) - apXStrings[g_numXStrings] = (char *)Xcalloc(MAXQUOTELEN,sizeof(uint8_t)); - } - + TArray buffer; while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) { - /* - if (*textptr == '%' && *(textptr+1) == 's') - { - initprintf("%s:%d: error: quote text contains string identifier.\n",g_szScriptFileName,g_lineNumber); - g_numCompilerErrors++; - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) textptr++; - break; - } - */ - if (tw == CON_DEFINEQUOTE) - *(apStrings[k]+i) = *textptr; - else - *(apXStrings[g_numXStrings]+i) = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= MAXQUOTELEN-1)) - { - initprintf("%s:%d: warning: truncating quote text to %d characters.\n",g_scriptFileName,g_lineNumber,MAXQUOTELEN-1); - g_warningCnt++; - scriptSkipLine(); - break; - } + buffer.Push(*textptr); + textptr++; } + buffer.Push(0); + if (tw == CON_DEFINEQUOTE) + quoteMgr.InitializeQuote(k, buffer.Data(), true); + else + quoteMgr.InitializeExQuote(k, buffer.Data(), true); - if (tw == CON_DEFINEQUOTE) + + if (tw != CON_DEFINEQUOTE) { - if ((unsigned)k < MAXQUOTES) - *(apStrings[k]+i) = '\0'; - } - else - { - *(apXStrings[g_numXStrings]+i) = '\0'; scriptWriteValue(g_numXStrings++); } continue; - + } case CON_DEFINECHEATDESCRIPTION: g_scriptPtr--; @@ -6009,14 +5846,7 @@ void C_PrintStats(void) MAXSPRITES * sizeof(spritetype)/(1<<6)), g_gameVarCount, MAXGAMEVARS, g_gameArrayCount, MAXGAMEARRAYS); - int cnt = g_numXStrings; - - for (auto &ptr : apStrings) - if (ptr) - cnt++; - - if (cnt) initprintf("%d strings, ", cnt); - cnt = 0; + int cnt = 0; for (auto & apScriptEvent : apScriptEvents) if (apScriptEvent) @@ -6080,7 +5910,7 @@ void C_Compile(const char *fileName) Gv_Init(); C_InitProjectiles(); - auto kFile = kopenFileReader(fileName,0); + auto kFile = fileSystem.OpenFileReader(fileName,0); if (!kFile.isOpen()) { diff --git a/source/duke3d/src/gamedef.h b/source/duke3d/src/gamedef.h index a9aa67294..f46bc8df0 100644 --- a/source/duke3d/src/gamedef.h +++ b/source/duke3d/src/gamedef.h @@ -212,18 +212,6 @@ void C_UndefineVolume(int32_t vol); void C_UndefineSkill(int32_t skill); void C_UndefineLevel(int32_t vol, int32_t lev); #if defined LUNATIC -void C_DefineSound(int32_t sndidx, const char *fn, int32_t args[5]); -void C_DefineQuote(int32_t qnum, const char *qstr); -void C_DefineVolumeName(int32_t vol, const char *name); -void C_DefineSkillName(int32_t skill, const char *name); -void C_DefineLevelName(int32_t vol, int32_t lev, const char *fn, - int32_t partime, int32_t designertime, - const char *levelname); -void C_DefineGameFuncName(int32_t idx, const char *name); -void C_DefineGameType(int32_t idx, int32_t flags, const char *name); -int32_t C_SetDefName(const char *name); -void C_DefineProjectile(int32_t j, int32_t what, int32_t val); -void C_SetCfgName(const char *cfgname); #else void C_ReportError(int error); void C_Compile(const char *filenam); diff --git a/source/duke3d/src/gameexec.cpp b/source/duke3d/src/gameexec.cpp index c5d614877..4c0df3108 100644 --- a/source/duke3d/src/gameexec.cpp +++ b/source/duke3d/src/gameexec.cpp @@ -37,8 +37,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "files.h" #include "base64.h" #include "version.h" +#include "menu/menu.h" +#include "c_dispatch.h" +#include "quotemgr.h" +#include "mapinfo.h" #include "debugbreak.h" +extern bool rotatesprite_2doverride; + +FString C_CON_GetBoundKeyForLastInput(int gameFunc); +const char* C_CON_GetButtonFunc(int num); BEGIN_DUKE_NS @@ -52,6 +60,8 @@ BEGIN_DUKE_NS vmstate_t vm; + + #if !defined LUNATIC int32_t g_tw; int32_t g_currentEvent = -1; @@ -74,7 +84,7 @@ int32_t g_structVarIDs = -1; uint32_t g_eventCalls[MAXEVENTS], g_actorCalls[MAXTILES]; double g_eventTotalMs[MAXEVENTS], g_actorTotalMs[MAXTILES], g_actorMinMs[MAXTILES], g_actorMaxMs[MAXTILES]; -GAMEEXEC_STATIC void VM_Execute(bool const loop = false); +GAMEEXEC_STATIC void VM_Execute(int const loop = false); # include "gamestructures.cpp" #endif @@ -159,7 +169,7 @@ static inline void VM_DummySprite(void) } // verification that the event actually exists happens elsewhere -static FORCE_INLINE int32_t VM_EventInlineInternal__(int const &eventNum, int const &spriteNum, int const &playerNum, +static FORCE_INLINE int32_t VM_EventInlineInternal__(int const eventNum, int const spriteNum, int const playerNum, int const playerDist = -1, int32_t returnValue = 0) { vmstate_t const newVMstate = { spriteNum, playerNum, playerDist, 0, @@ -235,7 +245,7 @@ int32_t VM_ExecuteEventWithValue(int const nEventID, int const spriteNum, int co } -static bool VM_CheckSquished(void) +static int VM_CheckSquished(void) { auto const pSector = (usectorptr_t)§or[vm.pSprite->sectnum]; @@ -289,7 +299,9 @@ GAMEEXEC_STATIC GAMEEXEC_INLINE void P_ForceAngle(DukePlayer_t *pPlayer) #endif // wow, this function sucks -bool A_Dodge(spritetype * const pSprite) + +int A_Dodge(spritetype * const); +int A_Dodge(spritetype * const pSprite) { if (A_CheckEnemySprite(pSprite) && pSprite->extra <= 0) // hack return 0; @@ -1059,17 +1071,17 @@ static void VM_Fall(int const spriteNum, spritetype * const pSprite) static int32_t VM_ResetPlayer(int const playerNum, int32_t vmFlags, int32_t const resetFlags) { - //AddLog("resetplayer"); + if (!g_netServer && ud.multimode < 2 && !(resetFlags & 2)) { - if (g_quickload && g_quickload->isValid() && ud.recstat != 2 && !(resetFlags & 8)) +#if 0 // Who thought that allowing a script to do this shit is a good idea??? This needs to be sorted out later and implemented properly. + if (!(resetFlags & 8)) { if (resetFlags & 4) { inputState.keyFlushChars(); inputState.ClearKeysDown(); FX_StopAllSounds(); - S_ClearSoundLocks(); if (G_LoadPlayerMaybeMulti(*g_quickload) != 0) { g_quickload->reset(); @@ -1078,20 +1090,23 @@ static int32_t VM_ResetPlayer(int const playerNum, int32_t vmFlags, int32_t cons } else if (!(resetFlags & 1)) { - Menu_Open(playerNum); - inputState.ClearKeyStatus(sc_Space); - I_AdvanceTriggerClear(); - Menu_Change(MENU_RESETPLAYER); + M_StartControlPanel(false); + M_SetMenu(NAME_ConfirmPlayerReset); + /* + case MENU_RESETPLAYER: + videoFadeToBlack(1); + Bsprintf(tempbuf, "Load last game:\n\"%s\"", g_quickload->name); + Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); + break; + */ } } else +#endif { - QuickLoadFailure: g_player[playerNum].ps->gm = MODE_RESTART; } -#if !defined LUNATIC vmFlags |= VM_NOEXECUTE; -#endif } else { @@ -1163,7 +1178,7 @@ static int G_StartTrackSlotWrap(int const volumeNum, int const levelNum) int G_StartTrack(int const levelNum) { return G_StartTrackSlot(ud.volume_number, levelNum); } #endif -LUNATIC_EXTERN void G_ShowView(vec3_t vec, fix16_t a, fix16_t horiz, int sect, int ix1, int iy1, int ix2, int iy2, bool unbiasedp) +LUNATIC_EXTERN void G_ShowView(vec3_t vec, fix16_t a, fix16_t horiz, int sect, int ix1, int iy1, int ix2, int iy2, int unbiasedp) { int x1 = min(ix1, ix2); int x2 = max(ix1, ix2); @@ -1218,13 +1233,17 @@ LUNATIC_EXTERN void G_ShowView(vec3_t vec, fix16_t a, fix16_t horiz, int sect, i renderSetAspect(viewingRange, yxAspect); } + void Screen_Play(void) { bool running = true; I_ClearAllInput(); - do + // This needs to be disabled during the loop. + auto r2dover = rotatesprite_2doverride; + rotatesprite_2doverride = false; + do { gameHandleEvents(); @@ -1241,6 +1260,7 @@ void Screen_Play(void) videoNextPage(); I_ClearAllInput(); } while (running); + rotatesprite_2doverride = r2dover; } #if !defined LUNATIC @@ -1288,7 +1308,7 @@ void Screen_Play(void) } \ } while (0) -GAMEEXEC_STATIC void VM_Execute(bool const loop /*= false*/) +GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/) { int vm_execution_depth = loop; #ifdef CON_USE_COMPUTED_GOTO @@ -2595,6 +2615,14 @@ GAMEEXEC_STATIC void VM_Execute(bool const loop /*= false*/) dispatch(); } +#define CON_FOR_ITERATION() \ + do \ + { \ + Gv_SetVar(returnVar, jj); \ + insptr = pNext; \ + VM_Execute(); \ + } while (0) + vInstruction(CON_FOR): // special-purpose iteration insptr++; { @@ -2612,113 +2640,76 @@ GAMEEXEC_STATIC void VM_Execute(bool const loop /*= false*/) { if (sprite[jj].statnum == MAXSTATUS) continue; - - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); + CON_FOR_ITERATION(); } break; + case ITER_ALLSPRITESBYSTAT: for (native_t statNum = 0; statNum < MAXSTATUS; ++statNum) { - for (native_t jj = headspritestat[statNum]; jj >= 0;) - { - int const kk = nextspritestat[jj]; - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); - jj = kk; - } + for (native_t jj = headspritestat[statNum], kk = nextspritestat[jj]; jj >= 0; jj = kk, kk = nextspritestat[jj]) + CON_FOR_ITERATION(); } break; + case ITER_ALLSPRITESBYSECT: for (native_t sectNum = 0; sectNum < numsectors; ++sectNum) { - for (native_t jj = headspritesect[sectNum]; jj >= 0;) - { - int const kk = nextspritesect[jj]; - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); - jj = kk; - } + for (native_t jj = headspritesect[sectNum], kk = nextspritesect[jj]; jj >= 0; jj = kk, kk = nextspritesect[jj]) + CON_FOR_ITERATION(); } break; + case ITER_ALLSECTORS: for (native_t jj = 0; jj < numsectors; ++jj) - { - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); - } + CON_FOR_ITERATION(); break; + case ITER_ALLWALLS: for (native_t jj = 0; jj < numwalls; ++jj) - { - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); - } + CON_FOR_ITERATION(); break; + case ITER_ACTIVELIGHTS: #ifdef POLYMER for (native_t jj = 0; jj < PR_MAXLIGHTS; ++jj) { if (!prlights[jj].flags.active) continue; - - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); + CON_FOR_ITERATION(); } #endif break; case ITER_DRAWNSPRITES: - { - for (native_t ii = 0; ii < spritesortcnt; ii++) - { - Gv_SetVar(returnVar, ii); - insptr = pNext; - VM_Execute(); - } + for (native_t jj = 0; jj < spritesortcnt; jj++) + CON_FOR_ITERATION(); break; - } case ITER_SPRITESOFSECTOR: if ((unsigned)nIndex >= MAXSECTORS) goto badindex; - for (native_t jj = headspritesect[nIndex]; jj >= 0;) - { - int const kk = nextspritesect[jj]; - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); - jj = kk; - } + + for (native_t jj = headspritesect[nIndex], kk = nextspritesect[jj]; jj >= 0; jj = kk, kk = nextspritesect[jj]) + CON_FOR_ITERATION(); break; + case ITER_SPRITESOFSTATUS: if ((unsigned)nIndex >= MAXSTATUS) goto badindex; - for (native_t jj = headspritestat[nIndex]; jj >= 0;) - { - int const kk = nextspritestat[jj]; - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); - jj = kk; - } + + for (native_t jj = headspritestat[nIndex], kk = nextspritestat[jj]; jj >= 0; jj = kk, kk = nextspritestat[jj]) + CON_FOR_ITERATION(); break; + case ITER_WALLSOFSECTOR: if ((unsigned)nIndex >= MAXSECTORS) goto badindex; + for (native_t jj = sector[nIndex].wallptr, endwall = jj + sector[nIndex].wallnum - 1; jj <= endwall; jj++) - { - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); - } + CON_FOR_ITERATION(); break; + case ITER_LOOPOFWALL: if ((unsigned)nIndex >= (unsigned)numwalls) goto badindex; @@ -2726,20 +2717,15 @@ GAMEEXEC_STATIC void VM_Execute(bool const loop /*= false*/) int jj = nIndex; do { - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); + CON_FOR_ITERATION(); jj = wall[jj].point2; } while (jj != nIndex); } break; + case ITER_RANGE: for (native_t jj = 0; jj < nIndex; jj++) - { - Gv_SetVar(returnVar, jj); - insptr = pNext; - VM_Execute(); - } + CON_FOR_ITERATION(); break; badindex: OSD_Printf(OSD_ERROR "Line %d, for %s: index %d out of range!\n", VM_DECODE_LINE_NUMBER(g_tw), iter_tokens[iterType].token, nIndex); @@ -2749,6 +2735,7 @@ badindex: insptr = pEnd; } dispatch(); +#undef CON_FOR_ITERATION vInstruction(CON_REDEFINEQUOTE): insptr++; @@ -2756,7 +2743,7 @@ badindex: int const strIndex = *insptr++; int const XstrIndex = *insptr++; - Bstrcpy(apStrings[strIndex], apXStrings[XstrIndex]); + quoteMgr.CopyExQuote(strIndex, XstrIndex); dispatch(); } @@ -3531,9 +3518,9 @@ badindex: int const gameVar = *insptr++; int const quoteNum = Gv_GetVar(*insptr++); - VM_ASSERT((unsigned)quoteNum < MAXQUOTES && apStrings[quoteNum], "invalid quote %d\n", quoteNum); + VM_ASSERT((unsigned)quoteNum < MAXQUOTES, "invalid quote %d\n", quoteNum); - Gv_SetVar(gameVar, Bstrlen(apStrings[quoteNum])); + Gv_SetVar(gameVar, strlen(quoteMgr.GetQuote(quoteNum))); dispatch(); } @@ -3556,11 +3543,11 @@ badindex: if (EDUKE32_PREDICT_FALSE(v.tileNum < 0 || v.tileNum + 127 >= MAXTILES)) CON_ERRPRINTF("invalid base tilenum %d\n", v.tileNum); - else if (EDUKE32_PREDICT_FALSE((unsigned)v.quoteNum >= MAXQUOTES || apStrings[v.quoteNum] == NULL)) + else if ((unsigned)v.quoteNum >= MAXQUOTES) CON_ERRPRINTF("invalid quote %d\n", v.quoteNum); else { - vec2_t dim = G_ScreenTextSize(v.tileNum, v.vect.x, v.vect.y, v.vect.z, v.blockAngle, apStrings[v.quoteNum], 2 | v.orientation, + vec2_t dim = G_ScreenTextSize(v.tileNum, v.vect.x, v.vect.y, v.vect.z, v.blockAngle, quoteMgr.GetQuote(v.quoteNum), 2 | v.orientation, v.offset.x, v.offset.y, v.between.x, v.between.y, v.f, v.bound[0].x, v.bound[0].y, v.bound[1].x, v.bound[1].y); @@ -3652,12 +3639,12 @@ badindex: int const quoteIndex = Gv_GetVar(*insptr++); int const gameFunc = Gv_GetVar(*insptr++); int funcPos = Gv_GetVar(*insptr++); - VM_ASSERT((unsigned)quoteIndex < MAXQUOTES && apStrings[quoteIndex], "invalid quote %d\n", quoteIndex); + VM_ASSERT((unsigned)quoteIndex < MAXQUOTES, "invalid quote %d\n", quoteIndex); VM_ASSERT((unsigned)gameFunc < NUMGAMEFUNCTIONS, "invalid function %d\n", gameFunc); - auto bindings = Bindings.GetKeysForCommand(buttonMap.GetButtonAlias(gameFunc)); + auto bindings = Bindings.GetKeysForCommand(C_CON_GetButtonFunc(gameFunc)); if ((unsigned)funcPos >= bindings.Size()) funcPos = 0; - Bstrcpy(apStrings[quoteIndex], KB_ScanCodeToString(bindings[funcPos])); + quoteMgr.InitializeQuote(quoteIndex, KB_ScanCodeToString(bindings[funcPos])); dispatch(); } @@ -3667,14 +3654,11 @@ badindex: int const quoteIndex = Gv_GetVar(*insptr++); int const gameFunc = Gv_GetVar(*insptr++); - VM_ASSERT((unsigned)quoteIndex < MAXQUOTES && apStrings[quoteIndex], "invalid quote %d\n", quoteIndex); + VM_ASSERT((unsigned)quoteIndex < MAXQUOTES, "invalid quote %d\n", quoteIndex); VM_ASSERT((unsigned)gameFunc < NUMGAMEFUNCTIONS, "invalid function %d\n", gameFunc); - static char const s_KeyboardFormat[] = "[%s]"; - static char const s_JoystickFormat[] = "(%s)"; - - auto binding = CONFIG_GetBoundKeyForLastInput(gameFunc); - if (binding.Len()) snprintf(apStrings[quoteIndex], MAXQUOTELEN, "(%s)", binding.GetChars()); + auto binding = C_CON_GetBoundKeyForLastInput(gameFunc); + if (binding.Len()) quoteMgr.FormatQuote(quoteIndex, "(%s)", binding.GetChars()); dispatch(); } @@ -3687,17 +3671,11 @@ badindex: } v; Gv_FillWithVars(v); - if (EDUKE32_PREDICT_FALSE((unsigned)v.outputQuote >= MAXQUOTES || apStrings[v.outputQuote] == NULL + if (EDUKE32_PREDICT_FALSE((unsigned)v.outputQuote >= MAXQUOTES || (unsigned)v.inputQuote >= MAXQUOTES - || apStrings[v.inputQuote] == NULL)) + )) { - CON_ERRPRINTF("invalid quote %d\n", apStrings[v.outputQuote] ? v.inputQuote : v.outputQuote); - abort_after_error(); - } - - if (EDUKE32_PREDICT_FALSE((unsigned)v.quotePos >= MAXQUOTELEN)) - { - CON_ERRPRINTF("invalid position %d\n", v.quotePos); + CON_ERRPRINTF("invalid quote %d\n", v.inputQuote >= MAXQUOTES ? v.inputQuote : v.outputQuote); abort_after_error(); } @@ -3707,18 +3685,18 @@ badindex: abort_after_error(); } - char * pOutput = apStrings[v.outputQuote]; - char const *pInput = apStrings[v.inputQuote]; + TArray output; + char const *pInput = quoteMgr.GetQuote(v.inputQuote); while (*pInput && v.quotePos--) pInput++; - while ((*pOutput = *pInput) && v.quoteLength--) + while ((*pInput) && v.quoteLength--) { - pOutput++; + output.Push(*pInput); pInput++; } - *pOutput = '\0'; - + output.Push(0); + quoteMgr.InitializeQuote(v.outputQuote, output.Data()); dispatch(); } @@ -3729,13 +3707,7 @@ badindex: int const quote2 = Gv_GetVar(*insptr++); int const gameVar = *insptr++; - if (EDUKE32_PREDICT_FALSE(apStrings[quote1] == NULL || apStrings[quote2] == NULL)) - { - CON_ERRPRINTF("null quote %d\n", apStrings[quote1] ? quote2 : quote1); - abort_after_error(); - } - - Gv_SetVar(gameVar, strcmp(apStrings[quote1], apStrings[quote2])); + Gv_SetVar(gameVar, strcmp(quoteMgr.GetQuote(quote1), quoteMgr.GetQuote(quote2))); dispatch(); } @@ -3759,14 +3731,14 @@ badindex: switch (VM_DECODE_INST(tw)) { case CON_GETPNAME: - VM_ASSERT((unsigned)q < MAXQUOTES && apStrings[q], "invalid quote %d\n", q); - if (g_player[j].user_name[0]) - Bstrcpy(apStrings[q], g_player[j].user_name); - else - Bsprintf(apStrings[q], "%d", j); + VM_ASSERT((unsigned)q < MAXQUOTES, "invalid quote %d\n", q); + if (g_player[j].user_name[0]) + quoteMgr.InitializeQuote(q, g_player[j].user_name); + else + quoteMgr.FormatQuote(q, "%d", j); break; case CON_QGETSYSSTR: - VM_ASSERT((unsigned)q < MAXQUOTES && apStrings[q], "invalid quote %d\n", q); + VM_ASSERT((unsigned)q < MAXQUOTES, "invalid quote %d\n", q); switch (j) { case STR_MAPNAME: @@ -3774,20 +3746,20 @@ badindex: { if (G_HaveUserMap()) { - snprintf(apStrings[q], MAXQUOTELEN, "%s", boardfilename); + quoteMgr.FormatQuote(q, "%s", boardfilename); break; } int const levelNum = ud.volume_number * MAXLEVELS + ud.level_number; const char *pName; - if (EDUKE32_PREDICT_FALSE((unsigned)levelNum >= ARRAY_SIZE(g_mapInfo))) + if (EDUKE32_PREDICT_FALSE((unsigned)levelNum >= ARRAY_SIZE(mapList))) { CON_ERRPRINTF("out of bounds map number (vol=%d, lev=%d)\n", ud.volume_number, ud.level_number); abort_after_error(); } - pName = j == STR_MAPNAME ? g_mapInfo[levelNum].name : g_mapInfo[levelNum].filename; + pName = j == STR_MAPNAME ? mapList[levelNum].DisplayName() : mapList[levelNum].fileName.GetChars(); if (EDUKE32_PREDICT_FALSE(pName == NULL)) { @@ -3796,22 +3768,22 @@ badindex: abort_after_error(); } - Bstrcpy(apStrings[q], j == STR_MAPNAME ? g_mapInfo[levelNum].name : g_mapInfo[levelNum].filename); + quoteMgr.InitializeQuote(q, j == STR_MAPNAME ? mapList[levelNum].DisplayName() : mapList[levelNum].fileName.GetChars()); break; } case STR_PLAYERNAME: VM_ASSERT((unsigned)vm.playerNum < (unsigned)g_mostConcurrentPlayers, "invalid player %d\n", vm.playerNum); - Bstrcpy(apStrings[q], g_player[vm.playerNum].user_name); + quoteMgr.InitializeQuote(q, g_player[vm.playerNum].user_name); break; case STR_VERSION: Bsprintf(tempbuf, HEAD2 " %s", GetGitDescription()); - Bstrcpy(apStrings[q], tempbuf); + quoteMgr.InitializeQuote(q, tempbuf); break; - case STR_GAMETYPE: Bstrcpy(apStrings[q], g_gametypeNames[ud.coop]); break; + case STR_GAMETYPE: quoteMgr.InitializeQuote(q, g_gametypeNames[ud.coop]); break; case STR_VOLUMENAME: if (G_HaveUserMap()) { - apStrings[q][0] = '\0'; + quoteMgr.InitializeQuote(q, ""); break; } @@ -3820,35 +3792,29 @@ badindex: CON_ERRPRINTF("invalid volume %d\n", ud.volume_number); abort_after_error(); } - Bstrcpy(apStrings[q], g_volumeNames[ud.volume_number]); + // length is no longer limited so a check is needed. + quoteMgr.InitializeQuote(q, gVolumeNames[ud.volume_number]); break; - case STR_YOURTIME: Bstrcpy(apStrings[q], G_PrintYourTime()); break; - case STR_PARTIME: Bstrcpy(apStrings[q], G_PrintParTime()); break; - case STR_DESIGNERTIME: Bstrcpy(apStrings[q], G_PrintDesignerTime()); break; - case STR_BESTTIME: Bstrcpy(apStrings[q], G_PrintBestTime()); break; - case STR_USERMAPFILENAME: snprintf(apStrings[q], MAXQUOTELEN, "%s", boardfilename); break; + case STR_YOURTIME: quoteMgr.InitializeQuote(q, G_PrintYourTime()); break; + case STR_PARTIME: quoteMgr.InitializeQuote(q, G_PrintParTime()); break; + case STR_DESIGNERTIME: quoteMgr.InitializeQuote(q, G_PrintDesignerTime()); break; + case STR_BESTTIME: quoteMgr.InitializeQuote(q, G_PrintBestTime()); break; + case STR_USERMAPFILENAME: quoteMgr.FormatQuote(q, "%s", boardfilename); break; default: CON_ERRPRINTF("invalid string index %d or %d\n", q, j); abort_after_error(); } break; case CON_QSTRCAT: - if (EDUKE32_PREDICT_FALSE(apStrings[q] == NULL || apStrings[j] == NULL)) - goto nullquote; - Bstrncat(apStrings[q], apStrings[j], (MAXQUOTELEN - 1) - Bstrlen(apStrings[q])); + quoteMgr.AppendQuote(q, j); break; case CON_QSTRNCAT: - if (EDUKE32_PREDICT_FALSE(apStrings[q] == NULL || apStrings[j] == NULL)) - goto nullquote; - Bstrncat(apStrings[q], apStrings[j], Gv_GetVar(*insptr++)); + quoteMgr.AppendQuote(q, j, Gv_GetVar(*insptr++)); break; case CON_QSTRCPY: - if (EDUKE32_PREDICT_FALSE(apStrings[q] == NULL || apStrings[j] == NULL)) - goto nullquote; - if (q != j) - Bstrcpy(apStrings[q], apStrings[j]); + if (q != j) + quoteMgr.CopyQuote(q, j); break; default: - nullquote: - CON_ERRPRINTF("invalid quote %d\n", apStrings[q] ? j : q); + CON_ERRPRINTF("invalid quote %d\n", q < MAXQUOTES? j : q); abort_after_error(); } dispatch(); @@ -4130,7 +4096,8 @@ badindex: vInstruction(CON_CMENU): insptr++; - Menu_Change(Gv_GetVar(*insptr++)); + // Well, sorry, but - no. + //Menu_Change(Gv_GetVar(*insptr++)); dispatch(); vInstruction(CON_SOUND): @@ -4169,18 +4136,18 @@ badindex: { int const nQuote = Gv_GetVar(*insptr++); - VM_ASSERT((unsigned)nQuote < MAXQUOTES && apStrings[nQuote], "invalid quote %d\n", nQuote); + VM_ASSERT((unsigned)nQuote < MAXQUOTES, "invalid quote %d\n", nQuote); if (VM_DECODE_INST(tw) == CON_IFCUTSCENE) { insptr--; - VM_CONDITIONAL(g_animPtr == Anim_Find(apStrings[nQuote])); + VM_CONDITIONAL(g_animPtr == Anim_Find(quoteMgr.GetQuote(nQuote))); dispatch(); } tw = vm.pPlayer->palette; I_ClearAllInput(); - Anim_Play(apStrings[nQuote]); + Anim_Play(quoteMgr.GetQuote(nQuote)); P_SetGamePalette(vm.pPlayer, tw, 2 + 16); dispatch(); } @@ -4323,9 +4290,9 @@ badindex: abort_after_error(); } - VM_ASSERT((unsigned)v.nQuote < MAXQUOTES && apStrings[v.nQuote], "invalid quote %d\n", v.nQuote); + VM_ASSERT((unsigned)v.nQuote < MAXQUOTES, "invalid quote %d\n", v.nQuote); - G_PrintGameText(v.tilenum, v.pos.x >> 1, v.pos.y, apStrings[v.nQuote], v.shade, v.pal, v.orientation & (ROTATESPRITE_MAX - 1), + G_PrintGameText(v.tilenum, v.pos.x >> 1, v.pos.y, quoteMgr.GetQuote(v.nQuote), v.shade, v.pal, v.orientation & (ROTATESPRITE_MAX - 1), v.bound[0].x, v.bound[0].y, v.bound[1].x, v.bound[1].y, z, 0); dispatch(); } @@ -4367,9 +4334,9 @@ badindex: } v; Gv_FillWithVars(v); - VM_ASSERT((unsigned)v.nQuote < MAXQUOTES && apStrings[v.nQuote], "invalid quote %d\n", v.nQuote); + VM_ASSERT((unsigned)v.nQuote < MAXQUOTES, "invalid quote %d\n", v.nQuote); - minitextshade(v.pos.x, v.pos.y, apStrings[v.nQuote], v.shade, v.pal, 2 + 8 + 16); + minitextshade(v.pos.x, v.pos.y, quoteMgr.GetQuote(v.nQuote), v.shade, v.pal, 2 + 8 + 16); dispatch(); } @@ -4393,9 +4360,9 @@ badindex: abort_after_error(); } - VM_ASSERT((unsigned)v.nQuote < MAXQUOTES && apStrings[v.nQuote], "invalid quote %d\n", v.nQuote); + VM_ASSERT((unsigned)v.nQuote < MAXQUOTES, "invalid quote %d\n", v.nQuote); - G_ScreenText(v.tilenum, v.v.x, v.v.y, v.v.z, v.blockangle, v.charangle, apStrings[v.nQuote], v.shade, v.pal, + G_ScreenText(v.tilenum, v.v.x, v.v.y, v.v.z, v.blockangle, v.charangle, quoteMgr.GetQuote(v.nQuote), v.shade, v.pal, 2 | (v.orientation & (ROTATESPRITE_MAX - 1)), v.alpha, v.spacing.x, v.spacing.y, v.between.x, v.between.y, v.nFlags, v.bound[0].x, v.bound[0].y, v.bound[1].x, v.bound[1].y); dispatch(); @@ -4795,9 +4762,9 @@ badindex: insptr++; int const nQuote = Gv_GetVar(*insptr++); - VM_ASSERT((unsigned)nQuote < MAXQUOTES && apStrings[nQuote], "invalid quote %d\n", nQuote); + VM_ASSERT((unsigned)nQuote < MAXQUOTES, "invalid quote %d\n", nQuote); - //communityapiUnlockAchievement(apStrings[nQuote]); + //communityapiUnlockAchievement(quoteMgr.GetQuote(v.nQuote)); dispatch(); } @@ -4807,9 +4774,9 @@ badindex: int const nQuote = Gv_GetVar(*insptr++); int const value = Gv_GetVar(*insptr++); - VM_ASSERT((unsigned)nQuote < MAXQUOTES && apStrings[nQuote], "invalid quote %d\n", nQuote); + VM_ASSERT((unsigned)nQuote < MAXQUOTES, "invalid quote %d\n", nQuote); - //communityapiSetStat(apStrings[nQuote], value); + //communityapiSetStat(quoteMgr.GetQuote(nQuote), value); dispatch(); } @@ -4878,32 +4845,9 @@ badindex: vInstruction(CON_SAVENN): vInstruction(CON_SAVE): insptr++; - { - int32_t const requestedSlot = *insptr++; - - if ((unsigned)requestedSlot >= 10) - dispatch(); - - // check if we need to make a new file - if (strcmp(g_lastautosave.path, g_lastusersave.path) == 0 || requestedSlot != g_lastAutoSaveArbitraryID) - { - g_lastautosave.reset(); - } - - g_lastAutoSaveArbitraryID = requestedSlot; - - if (VM_DECODE_INST(tw) == CON_SAVE || g_lastautosave.name[0] == 0) - { - time_t timeStruct = time(NULL); - struct tm *pTime = localtime(&timeStruct); - - strftime(g_lastautosave.name, sizeof(g_lastautosave.name), "%d %b %Y %I:%M%p", pTime); - } - - g_saveRequested = true; - - dispatch(); - } + insptr++; // skip the slot. I will not allow the script to do targeted saving without user control. + g_saveRequested = true; // cannot save right here. + dispatch(); vInstruction(CON_QUAKE): insptr++; @@ -5034,7 +4978,7 @@ badindex: vInstruction(CON_STOPALLMUSIC): insptr++; - S_StopMusic(); + Mus_Stop(); dispatch(); vInstruction(CON_OPERATE): @@ -5107,16 +5051,10 @@ badindex: int const outputQuote = Gv_GetVar(*insptr++); int const inputQuote = Gv_GetVar(*insptr++); - if (EDUKE32_PREDICT_FALSE(apStrings[inputQuote] == NULL || apStrings[outputQuote] == NULL)) - { - CON_ERRPRINTF("null quote %d\n", apStrings[inputQuote] ? outputQuote : inputQuote); - abort_after_error(); - } - - auto &inBuf = apStrings[inputQuote]; + auto inBuf = quoteMgr.GetQuote(inputQuote); int32_t arg[32]; - char outBuf[MAXQUOTELEN]; + TArray outBuf; int const quoteLen = Bstrlen(inBuf); @@ -5135,8 +5073,8 @@ badindex: do { - while (inputPos < quoteLen && outputPos < MAXQUOTELEN && inBuf[inputPos] != '%') - outBuf[outputPos++] = inBuf[inputPos++]; + while (inputPos < quoteLen && inBuf[inputPos] != '%') + outBuf.Push(inBuf[inputPos++]); if (inBuf[inputPos] == '%') { @@ -5147,8 +5085,8 @@ badindex: if (inBuf[inputPos + 1] != 'd') { // write the % and l - outBuf[outputPos++] = inBuf[inputPos - 1]; - outBuf[outputPos++] = inBuf[inputPos++]; + outBuf.Push(inBuf[inputPos - 1]); + outBuf.Push(inBuf[inputPos++]); break; } inputPos++; @@ -5162,7 +5100,8 @@ badindex: Bsprintf(buf, "%d", arg[argIdx++]); int const bufLen = Bstrlen(buf); - Bmemcpy(&outBuf[outputPos], buf, bufLen); + outputPos = outBuf.Reserve(bufLen); + memcpy(&outBuf[outputPos], buf, bufLen); outputPos += bufLen; inputPos++; } @@ -5173,22 +5112,24 @@ badindex: if (argIdx >= numArgs) goto finish_qsprintf; - int const argLen = Bstrlen(apStrings[arg[argIdx]]); + auto quoteArg = quoteMgr.GetQuote(arg[argIdx]); + int const argLen = (int)strlen(quoteArg); - Bmemcpy(&outBuf[outputPos], apStrings[arg[argIdx]], argLen); + outputPos = outBuf.Reserve(argLen); + memcpy(&outBuf[outputPos], quoteArg, argLen); outputPos += argLen; argIdx++; inputPos++; } break; - default: outBuf[outputPos++] = inBuf[inputPos - 1]; break; + default: outBuf.Push(inBuf[inputPos - 1]); break; } } - } while (inputPos < quoteLen && outputPos < MAXQUOTELEN); + } while (inputPos < quoteLen); finish_qsprintf: - outBuf[outputPos] = '\0'; - Bstrncpyz(apStrings[outputQuote], outBuf, MAXQUOTELEN); + outBuf.Push(0); + quoteMgr.InitializeQuote(outputQuote, outBuf.Data()); dispatch(); } @@ -5309,7 +5250,7 @@ badindex: // -1 for none found // int const decodedInst = VM_DECODE_INST(tw); - bool const actorsOnly = (decodedInst == CON_FINDNEARACTOR || decodedInst == CON_FINDNEARACTOR3D); + int const actorsOnly = (decodedInst == CON_FINDNEARACTOR || decodedInst == CON_FINDNEARACTOR3D); auto const dist_funcptr = (decodedInst == CON_FINDNEARACTOR || decodedInst == CON_FINDNEARSPRITE) ? &ldist : &dist; int const findTile = *insptr++; @@ -5357,7 +5298,7 @@ badindex: // that is of into // -1 for none found // - bool const actorsOnly = (VM_DECODE_INST(tw) == CON_FINDNEARACTORZ); + int const actorsOnly = (VM_DECODE_INST(tw) == CON_FINDNEARACTORZ); int const findTile = *insptr++; int maxDist = Gv_GetVar(*insptr++); @@ -5604,9 +5545,9 @@ badindex: int const arrayNum = *insptr++; int const quoteFilename = *insptr++; - VM_ASSERT((unsigned)quoteFilename < MAXQUOTES && apStrings[quoteFilename], "invalid quote %d\n", quoteFilename); + VM_ASSERT((unsigned)quoteFilename < MAXQUOTES, "invalid quote %d\n", quoteFilename); FStringf IniSection("%s.UserStrings", LumpFilter.GetChars()); - auto IniKey = apStrings[quoteFilename]; + auto IniKey = quoteMgr.GetQuote(quoteFilename); if (!GameConfig->SetSection(IniSection)) { dispatch(); @@ -5680,12 +5621,12 @@ badindex: int const arrayNum = *insptr++; int const quoteFilename = *insptr++; - VM_ASSERT((unsigned)quoteFilename < MAXQUOTES && apStrings[quoteFilename], "invalid quote %d\n", quoteFilename); + VM_ASSERT((unsigned)quoteFilename < MAXQUOTES, "invalid quote %d\n", quoteFilename); // No, we are not writing stuff to an arbitrary file on the hard drive! This is a first grade exploit for doing serious damage. // Instead, encode the data as BASE64 and write it to the config file, // which doesn't create a wide open door for exploits. FStringf IniSection("%s.UserStrings", LumpFilter.GetChars()); - auto IniKey = apStrings[quoteFilename]; + auto IniKey = quoteMgr.GetQuote(quoteFilename); BufferWriter bw; switch (aGameArrays[arrayNum].flags & GAMEARRAY_SIZE_MASK) @@ -6202,18 +6143,18 @@ badindex: insptr++; tw = Gv_GetVar(*insptr++); - VM_ASSERT((unsigned)tw < MAXQUOTES && apStrings[tw], "invalid quote %d\n", (int)tw); + VM_ASSERT((unsigned)tw < MAXQUOTES, "invalid quote %d\n", (int)tw); - G_AddUserQuote(apStrings[tw]); + G_AddUserQuote(quoteMgr.GetQuote(tw)); dispatch(); vInstruction(CON_ECHO): insptr++; tw = Gv_GetVar(*insptr++); - VM_ASSERT((unsigned)tw < MAXQUOTES && apStrings[tw], "invalid quote %d\n", (int)tw); + VM_ASSERT((unsigned)tw < MAXQUOTES, "invalid quote %d\n", (int)tw); - OSD_Printf("%s\n", apStrings[tw]); + OSD_Printf("%s\n", quoteMgr.GetQuote(tw)); dispatch(); vInstruction(CON_RESPAWNHITAG): diff --git a/source/duke3d/src/gameexec.h b/source/duke3d/src/gameexec.h index 513672223..55939578f 100644 --- a/source/duke3d/src/gameexec.h +++ b/source/duke3d/src/gameexec.h @@ -35,7 +35,7 @@ int32_t VM_ExecuteEvent(int const nEventID, int const spriteNum, int const playe int32_t VM_ExecuteEvent(int const nEventID, int const spriteNum, int const playerNum); int32_t VM_ExecuteEventWithValue(int const nEventID, int const spriteNum, int const playerNum, int32_t const nReturn); -static FORCE_INLINE bool VM_HaveEvent(int const nEventID) +static FORCE_INLINE int VM_HaveEvent(int const nEventID) { return !!apScriptEvents[nEventID]; } diff --git a/source/duke3d/src/gamestructures.cpp b/source/duke3d/src/gamestructures.cpp index da3abf8b6..9ea044ae4 100644 --- a/source/duke3d/src/gamestructures.cpp +++ b/source/duke3d/src/gamestructures.cpp @@ -915,11 +915,13 @@ void __fastcall VM_SetPlayer(int const playerNum, int const labelNum, int const break; case PLAYER_GM: + /* WTF?!? if (!(ps.gm & MODE_MENU) && (newValue & MODE_MENU)) Menu_Open(playerNum); else if ((ps.gm & MODE_MENU) && !(newValue & MODE_MENU)) Menu_Close(playerNum); - ps.gm = newValue; + */ + ps.gm = (newValue & ~MODE_MENU) | (ps.gm & MODE_MENU); break; case PLAYER_GOTWEAPON: @@ -1448,7 +1450,7 @@ int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2) case USERDEFS_MOUSEFLIP: labelNum = !in_mouseflip; break; case USERDEFS_STATUSBARSCALE: labelNum = ud.statusbarscale; break; case USERDEFS_DRAWWEAPON: labelNum = r_drawweapon; break; - case USERDEFS_MOUSEAIMING: labelNum = in_aimmode; break; + case USERDEFS_MOUSEAIMING: labelNum = in_mousemode; break; case USERDEFS_WEAPONSWITCH: labelNum = cl_weaponswitch; break; case USERDEFS_DEMOCAMS: labelNum = cl_democams; break; case USERDEFS_COLOR: labelNum = playercolor; break; @@ -1506,8 +1508,8 @@ int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2) case USERDEFS_GLOBAL_R: labelNum = globalr; break; case USERDEFS_GLOBAL_G: labelNum = globalg; break; case USERDEFS_GLOBAL_B: labelNum = globalb; break; - case USERDEFS_DEFAULT_VOLUME: labelNum = ud.default_volume; break; - case USERDEFS_DEFAULT_SKILL: labelNum = ud.default_skill; break; + case USERDEFS_DEFAULT_VOLUME: labelNum = gDefaultVolume; break; + case USERDEFS_DEFAULT_SKILL: labelNum = gDefaultSkill; break; case USERDEFS_MENU_SHADEDESELECTED: labelNum = MF_Redfont.shade_deselected; break; case USERDEFS_MENU_SHADEDISABLED: labelNum = MF_Redfont.shade_disabled; break; case USERDEFS_MENUTEXT_ZOOM: labelNum = MF_Redfont.zoom; break; @@ -1529,7 +1531,7 @@ int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2) case USERDEFS_MENUTITLE_PAL: labelNum = ud.menutitle_pal; break; case USERDEFS_SLIDEBAR_PALSELECTED: labelNum = ud.slidebar_palselected; break; case USERDEFS_SLIDEBAR_PALDISABLED: labelNum = ud.slidebar_paldisabled; break; - case USERDEFS_MUSIC_EPISODE: labelNum = ud.music_episode; break; + case USERDEFS_MUSIC_EPISODE: labelNum = ud.music_episode; break; // Problem: This info is utterly meaningless with the new music system. case USERDEFS_MUSIC_LEVEL: labelNum = ud.music_level; break; case USERDEFS_SHADOW_PAL: labelNum = ud.shadow_pal; break; case USERDEFS_MENU_SCROLLBARTILENUM: labelNum = ud.menu_scrollbartilenum; break; @@ -1630,8 +1632,8 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_M_FFIRE: m_ffire = iSet; break; case USERDEFS_FFIRE: ud.ffire = iSet; break; case USERDEFS_M_PLAYER_SKILL: ud.m_player_skill = iSet; break; - case USERDEFS_M_LEVEL_NUMBER: m_level_number = iSet; break; - case USERDEFS_M_VOLUME_NUMBER: ud.m_volume_number = iSet; break; + case USERDEFS_M_LEVEL_NUMBER: GameStartupInfo.Level = m_level_number = iSet; break; + case USERDEFS_M_VOLUME_NUMBER: GameStartupInfo.Episode = ud.m_volume_number = iSet; break; case USERDEFS_MULTIMODE: ud.multimode = iSet; break; case USERDEFS_PLAYER_SKILL: ud.player_skill = iSet; break; case USERDEFS_LEVEL_NUMBER: ud.level_number = iSet; break; @@ -1641,10 +1643,10 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_MOUSEFLIP: in_mouseflip.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_STATUSBARSCALE: ud.statusbarscale = iSet; break; case USERDEFS_DRAWWEAPON: r_drawweapon.SetGenericRepDefault(iSet, CVAR_Int); break; - case USERDEFS_MOUSEAIMING: in_aimmode.SetGenericRepDefault(iSet, CVAR_Int); break; + case USERDEFS_MOUSEAIMING: break; // the script code has no business whatsoever changing this! case USERDEFS_WEAPONSWITCH: cl_weaponswitch.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_DEMOCAMS: cl_democams = iSet; break; - case USERDEFS_COLOR: playercolor = iSet; break; + case USERDEFS_COLOR: /*playercolor.SetGenericRepDefault(iSet, CVAR_Int);*/ break; // the value range here does not match, so better leave the CVar alone. case USERDEFS_MSGDISPTIME: hud_messagetime.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_STATUSBARMODE: ud.statusbarmode = iSet; break; case USERDEFS_M_NOEXITS: m_noexits = iSet; break; @@ -1652,7 +1654,7 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_AUTOVOTE: cl_autovote.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_AUTOMSG: cl_automsg.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_IDPLAYERS: cl_idplayers.SetGenericRepDefault(iSet, CVAR_Int); break; - case USERDEFS_TEAM: playerteam = iSet; break; + case USERDEFS_TEAM: playerteam.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_VIEWBOB: cl_viewbob.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_WEAPONSWAY: cl_weaponsway.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_ANGLEINTERPOLATION: ud.angleinterpolation = iSet; break; @@ -1699,8 +1701,8 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_GLOBAL_R: globalr = iSet; break; case USERDEFS_GLOBAL_G: globalg = iSet; break; case USERDEFS_GLOBAL_B: globalb = iSet; break; - case USERDEFS_DEFAULT_VOLUME: ud.default_volume = iSet; break; - case USERDEFS_DEFAULT_SKILL: ud.default_skill = iSet; break; + case USERDEFS_DEFAULT_VOLUME: gDefaultVolume = iSet; break; + case USERDEFS_DEFAULT_SKILL: gDefaultSkill = iSet; break; case USERDEFS_MENU_SHADEDESELECTED: MF_Redfont.shade_deselected = MF_Bluefont.shade_deselected = MF_Minifont.shade_deselected = iSet; break; case USERDEFS_MENU_SHADEDISABLED: MF_Redfont.shade_disabled = MF_Bluefont.shade_disabled = MF_Minifont.shade_disabled = iSet; break; case USERDEFS_MENUTEXT_ZOOM: MF_Redfont.zoom = iSet; break; @@ -1749,16 +1751,8 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_DRAW_Y: rotatesprite_y_offset = iSet; break; case USERDEFS_DRAW_YXASPECT: rotatesprite_yxaspect = iSet; break; case USERDEFS_FOV: r_fov.SetGenericRepDefault(iSet, CVAR_Int); break; - case USERDEFS_NEWGAMECUSTOMOPEN: - for (unsigned int b = 0; b < MAXMENUGAMEPLAYENTRIES; ++b) - if (iSet & (1u<D aGameVars[Gv_GetVarIndex("lastvisinc")].global = (intptr_t)&lastvisinc; aGameVars[Gv_GetVarIndex("looking_angSR1")].global = (intptr_t)&hudweap.lookhalfang; aGameVars[Gv_GetVarIndex("looking_arc")].global = (intptr_t)&hudweap.lookhoriz; diff --git a/source/duke3d/src/gamevars.h b/source/duke3d/src/gamevars.h index 66d0b8e22..c45c194e1 100644 --- a/source/duke3d/src/gamevars.h +++ b/source/duke3d/src/gamevars.h @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "fix16.hpp" #include "gamedef.h" +#include "filesystem/filesystem.h" BEGIN_DUKE_NS @@ -207,82 +208,74 @@ static FORCE_INLINE void __fastcall VM_SetStruct(uint32_t const flags, intptr_t } } -#define VM_GAMEVAR_OPERATOR(func, operator) \ - static FORCE_INLINE void __fastcall func(int const id, int32_t const operand) \ - { \ - auto &var = aGameVars[id]; \ - \ - switch (var.flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) \ - { \ - default: var.global operator operand; break; \ - case GAMEVAR_PERPLAYER: \ - if (EDUKE32_PREDICT_FALSE((unsigned)vm.playerNum > MAXPLAYERS - 1)) \ - break; \ - var.pValues[vm.playerNum] operator operand; \ - break; \ - case GAMEVAR_PERACTOR: \ - if (EDUKE32_PREDICT_FALSE((unsigned)vm.spriteNum > MAXSPRITES - 1)) \ - break; \ - var.pValues[vm.spriteNum] operator operand; \ - break; \ - case GAMEVAR_INT32PTR: *(int32_t *)var.pValues operator(int32_t) operand; break; \ - case GAMEVAR_INT16PTR: *(int16_t *)var.pValues operator(int16_t) operand; break; \ - case GAMEVAR_Q16PTR: \ - { \ - Fix16 *pfix = (Fix16 *)var.global; \ - *pfix operator fix16_from_int(operand); \ - break; \ - } \ - } \ +#define VM_GAMEVAR_OPERATOR(func, operator) \ + static FORCE_INLINE ATTRIBUTE((flatten)) void __fastcall func(int const id, int32_t const operand) \ + { \ + auto &var = aGameVars[id]; \ + \ + switch (var.flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) \ + { \ + default: \ + var.global operator operand; \ + break; \ + case GAMEVAR_PERPLAYER: \ + var.pValues[vm.playerNum & (MAXPLAYERS-1)] operator operand; \ + break; \ + case GAMEVAR_PERACTOR: \ + var.pValues[vm.spriteNum & (MAXSPRITES-1)] operator operand; \ + break; \ + case GAMEVAR_INT32PTR: *(int32_t *)var.pValues operator(int32_t) operand; break; \ + case GAMEVAR_INT16PTR: *(int16_t *)var.pValues operator(int16_t) operand; break; \ + case GAMEVAR_Q16PTR: \ + { \ + Fix16 *pfix = (Fix16 *)var.global; \ + *pfix operator fix16_from_int(operand); \ + break; \ + } \ + } \ } -static FORCE_INLINE void __fastcall Gv_DivVar(int const id, int32_t const operand) +static FORCE_INLINE void __fastcall Gv_DivVar(int const id, int32_t const d) { - auto &var = aGameVars[id]; + using namespace libdivide; - if (EDUKE32_PREDICT_FALSE((var.flags & GAMEVAR_PERPLAYER && (unsigned) vm.playerNum > MAXPLAYERS - 1) || - (var.flags & GAMEVAR_PERACTOR && (unsigned) vm.spriteNum > MAXSPRITES - 1))) - return; - - bool const foundInTable = (unsigned) operand < DIVTABLESIZE; - static libdivide::libdivide_s32_t sdiv; - intptr_t *iptr = &var.global; + static libdivide_s32_t sdiv; static int32_t lastValue; - auto dptr = foundInTable ? (libdivide::libdivide_s32_t *) &divtable32[operand] : &sdiv; - if (operand == lastValue || foundInTable) - goto skip; + auto &var = aGameVars[id]; + auto *dptr = &sdiv; + auto iptr = &var.global; - sdiv = libdivide::libdivide_s32_gen((lastValue = operand)); - -skip: + if ((unsigned)d < DIVTABLESIZE) + dptr = &divtable32[d]; + else if (d != lastValue) + sdiv = libdivide_s32_gen((lastValue = d)); + switch (var.flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) { - case GAMEVAR_PERACTOR: iptr = &var.pValues[vm.spriteNum]; break; - case GAMEVAR_PERPLAYER: iptr = &var.pValues[vm.playerNum]; - default: break; + case GAMEVAR_PERACTOR: iptr = &var.pValues[vm.spriteNum & (MAXSPRITES-1)]; goto jmp; + case GAMEVAR_PERPLAYER: iptr = &var.pValues[vm.playerNum & (MAXPLAYERS-1)]; fallthrough__; + jmp: default: *iptr = libdivide_s32_do(*iptr, dptr); break; case GAMEVAR_INT32PTR: { - int32_t &value = *(int32_t *)var.pValues; - value = (int32_t)libdivide::libdivide_s32_do(value, dptr); - return; + auto &value = *(int32_t *)var.pValues; + value = libdivide_s32_do(value, dptr); + break; } case GAMEVAR_INT16PTR: { - int16_t &value = *(int16_t *)var.pValues; - value = (int16_t)libdivide::libdivide_s32_do(value, dptr); - return; + auto &value = *(int16_t *)var.pValues; + value = (int16_t)libdivide_s32_do(value, dptr); + break; } case GAMEVAR_Q16PTR: { - fix16_t &value = *(fix16_t *)var.pValues; - value = fix16_div(value, fix16_from_int(operand)); - return; + auto &value = *(fix16_t *)var.pValues; + value = fix16_div(value, fix16_from_int(d)); + break; } } - - *iptr = libdivide_s32_do(*iptr, dptr); } VM_GAMEVAR_OPERATOR(Gv_AddVar, +=) diff --git a/source/duke3d/src/global.cpp b/source/duke3d/src/global.cpp index 6cb1673b6..efddc8e1d 100644 --- a/source/duke3d/src/global.cpp +++ b/source/duke3d/src/global.cpp @@ -34,19 +34,9 @@ user_defs ud; const char *s_buildDate = "20120522"; -#ifndef EDUKE32_STANDALONE -char g_volumeNames[MAXVOLUMES][33] = { "L.A. Meltdown", "Lunar Apocalypse", "Shrapnel City" }; -char g_skillNames[MAXSKILLS][33] = { "Piece Of Cake", "Let's Rock", "Come Get Some", "Damn I'm Good" }; char g_gametypeNames[MAXGAMETYPES][33] -= { "DukeMatch (Spawn)", "Cooperative Play", "DukeMatch (No Spawn)", "Team DM (Spawn)", "Team DM (No Spawn)" }; -#else -char g_volumeNames[MAXVOLUMES][33]; -char g_skillNames[MAXSKILLS][33]; -char g_gametypeNames[MAXGAMETYPES][33] -= { "Deathmatch (Spawn)", "Cooperative Play", "Deathmatch (No Spawn)", "Team DM (Spawn)", "Team DM (No Spawn)" }; -#endif += { "$NETMNU_GAMETYPE1", "$NETMNU_GAMETYPE2", "NETMNU_GAMETYPE3", "NETMNU_GAMETYPE4", "NETMNU_GAMETYPE5" }; -int32_t g_volumeFlags[MAXVOLUMES]; int32_t g_gametypeFlags[MAXGAMETYPES] = { diff --git a/source/duke3d/src/global.h b/source/duke3d/src/global.h index f50f685ff..bfb84f74c 100644 --- a/source/duke3d/src/global.h +++ b/source/duke3d/src/global.h @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "quotes.h" #include "sector.h" #include "sounds.h" +#include "menu/menu.h" BEGIN_DUKE_NS @@ -41,7 +42,6 @@ BEGIN_DUKE_NS #define MAXINTERPOLATIONS MAXSPRITES // KEEPINSYNC lunatic/con_lang.lua -#define MAXSKILLS 7 // duke3d global soup :( @@ -67,9 +67,7 @@ G_EXTERN actor_t actor[MAXSPRITES]; // g_tile: tile-specific data THAT DOES NOT CHANGE during the course of a game G_EXTERN tiledata_t g_tile[MAXTILES]; G_EXTERN animwalltype animwall[MAXANIMWALLS]; -G_EXTERN char *apStrings[MAXQUOTES],*apXStrings[MAXQUOTES]; G_EXTERN char *label; -G_EXTERN int32_t g_musicIndex; G_EXTERN char g_loadFromGroupOnly; G_EXTERN char g_skillCnt; G_EXTERN char pus,pub; @@ -147,7 +145,6 @@ G_EXTERN playerspawn_t g_playerSpawnPoints[MAXPLAYERS]; G_EXTERN input_t inputfifo[MOVEFIFOSIZ][MAXPLAYERS]; #pragma pack(pop) -G_EXTERN uint8_t g_soundlocks[MAXSOUNDS]; G_EXTERN int32_t g_noEnemies; G_EXTERN int32_t g_restorePalette; G_EXTERN int32_t g_screenCapture; @@ -163,8 +160,6 @@ extern double g_gameUpdateAvgTime; #ifndef global_c_ extern char CheatKeys[2]; extern char g_gametypeNames[MAXGAMETYPES][33]; -extern char g_skillNames[MAXSKILLS][33]; -extern char g_volumeNames[MAXVOLUMES][33]; extern int32_t g_actorRespawnTime; extern int32_t g_bouncemineRadius; @@ -186,17 +181,11 @@ extern int32_t g_volumeCnt; extern int16_t g_blimpSpawnItems[15]; extern int32_t g_gametypeFlags[MAXGAMETYPES]; -extern int32_t g_volumeFlags[MAXVOLUMES]; + extern const char *s_buildDate; #endif -enum -{ - EF_HIDEFROMSP = 1<<0, - // EF_HIDEFROMMP = 1<<1, -}; - EXTERN_INLINE_HEADER void G_UpdateInterpolations(void); EXTERN_INLINE_HEADER void G_RestoreInterpolations(void); diff --git a/source/duke3d/src/menus.cpp b/source/duke3d/src/menus.cpp index 4701f1ba1..a57589d3c 100644 --- a/source/duke3d/src/menus.cpp +++ b/source/duke3d/src/menus.cpp @@ -45,1755 +45,13 @@ namespace ImGui BEGIN_DUKE_NS +#if 0 -// common positions -#define MENU_MARGIN_REGULAR 40 -#define MENU_MARGIN_WIDE 32 -#define MENU_MARGIN_CENTER 160 -#define MENU_HEIGHT_CENTER 100 - -#define USERMAPENTRYLENGTH 25 - -static FORCE_INLINE void Menu_StartTextInput() -{ - inputState.keyFlushChars(); - inputState.ClearKeysDown(); -} - -static FORCE_INLINE void Menu_StopTextInput() -{ -} - -static FORCE_INLINE void rotatesprite_ybounds(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, int32_t ydim_upper, int32_t ydim_lower) -{ - rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, 0, ydim_upper, xdim-1, ydim_lower); -} - -static void mgametext(int32_t x, int32_t y, char const * t) -{ - G_ScreenText(MF_Bluefont.tilenum, x, y, MF_Bluefont.zoom, 0, 0, t, 0, MF_Bluefont.pal, 2|8|16|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags, 0, 0, xdim-1, ydim-1); -} - -static vec2_t mgametextcenterat(int32_t x, int32_t y, char const * t, int32_t f = 0) -{ - return G_ScreenText(MF_Bluefont.tilenum, x, y, MF_Bluefont.zoom, 0, 0, t, 0, MF_Bluefont.pal, 2|8|16|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags|f|TEXT_XCENTER, 0, 0, xdim-1, ydim-1); -} -static vec2_t mgametextcenter(int32_t x, int32_t y, char const * t, int32_t f = 0) -{ - return mgametextcenterat((MENU_MARGIN_CENTER<<16) + x, y, t, f); -} - -#define mminitext(x,y,t,p) minitext_(x, y, t, 0, p, 2|8|16|ROTATESPRITE_FULL16) -#define mmenutext menutext - -#ifndef EDUKE32_STANDALONE -static void shadowminitext(int32_t x, int32_t y, const char *t, int32_t p) -{ - int32_t f = 0; - - if (!minitext_lowercase) - f |= TEXT_UPPERCASE; - - G_ScreenTextShadow(1, 1, MINIFONT, x, y, 65536, 0, 0, t, 0, p, 2|8|16|ROTATESPRITE_FULL16, 0, 4<<16, 8<<16, 1<<16, 0, f, 0, 0, xdim-1, ydim-1); -} -#endif -static void creditsminitext(int32_t x, int32_t y, const char *t, int32_t p) -{ - int32_t f = TEXT_XCENTER; - - if (!minitext_lowercase) - f |= TEXT_UPPERCASE; - - G_ScreenTextShadow(1, 1, MINIFONT, x, y, 65536, 0, 0, t, 0, p, 2|8|16|ROTATESPRITE_FULL16, 0, 4<<16, 8<<16, 1<<16, 0, f, 0, 0, xdim-1, ydim-1); -} - -#pragma pack(push,1) -static savehead_t savehead; -#pragma pack(pop) - -static void Menu_DrawBackground(const vec2_t origin) -{ - rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (100<<16), 65536L,0,MENUSCREEN,16,0,10+64); -} - -static void Menu_DrawTopBar(const vec2_t origin) -{ - if ((G_GetLogoFlags() & LOGO_NOTITLEBAR) == 0) - rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (19<<16), MF_Redfont.cursorScale, 0,MENUBAR,16,0,10); -} - -static void Menu_DrawTopBarCaption(const char *caption, const vec2_t origin) -{ - static char t[64]; - size_t const srclen = strlen(caption); - size_t const dstlen = min(srclen, ARRAY_SIZE(t)-1); - memcpy(t, caption, dstlen); - t[dstlen] = '\0'; - char *p = &t[dstlen-1]; - if (*p == ':') - *p = '\0'; - captionmenutext(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (24<<16) + ((15>>1)<<16), t); -} - -static FORCE_INLINE int32_t Menu_CursorShade(void) -{ - return VM_OnEventWithReturn(EVENT_MENUCURSORSHADE, -1, myconnectindex, 4-(sintable[((int32_t) totalclock<<4)&2047]>>11)); -} -static void Menu_DrawCursorCommon(int32_t x, int32_t y, int32_t z, int32_t picnum, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1) -{ - rotatesprite_(x, y, z, 0, picnum, Menu_CursorShade(), 0, 2|8, 0, 0, 0, ydim_upper, xdim-1, ydim_lower); -} -static void Menu_DrawCursorLeft(int32_t x, int32_t y, int32_t z) -{ - if (FURY) return; - Menu_DrawCursorCommon(x, y, z, VM_OnEventWithReturn(EVENT_MENUCURSORLEFT, -1, myconnectindex, SPINNINGNUKEICON+(((int32_t) totalclock>>3)%7))); -} -static void Menu_DrawCursorRight(int32_t x, int32_t y, int32_t z) -{ - if (FURY) return; - Menu_DrawCursorCommon(x, y, z, VM_OnEventWithReturn(EVENT_MENUCURSORRIGHT, -1, myconnectindex, SPINNINGNUKEICON+6-((6+((int32_t) totalclock>>3))%7))); -} -static void Menu_DrawCursorTextTile(int32_t x, int32_t y, int32_t h, int32_t picnum, vec2_16_t const & siz, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1) -{ - vec2_t const adjsiz = { (siz.x>>1)<<16, siz.y<<16 }; - Menu_DrawCursorCommon(x + scale(adjsiz.x, h, adjsiz.y), y, divscale16(h, adjsiz.y), picnum, ydim_upper, ydim_lower); -} -static void Menu_DrawCursorText(int32_t x, int32_t y, int32_t h, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1) -{ - vec2_16_t const & siz = tilesiz[SPINNINGNUKEICON]; - - if (FURY || siz.x == 0) - { - Menu_DrawCursorTextTile(x, y, h, SMALLFNTCURSOR, tilesiz[SMALLFNTCURSOR], ydim_upper, ydim_lower); - return; - } - - Menu_DrawCursorTextTile(x, y, h, SPINNINGNUKEICON+(((int32_t) totalclock>>3)%7), siz, ydim_upper, ydim_lower); -} - - -static uint16_t g_oldSaveCnt; - - - - -/* -All MAKE_* macros are generally for the purpose of keeping state initialization -separate from actual data. Alternatively, they can serve to factor out repetitive -stuff and keep the important bits from getting lost to our eyes. - -They serve as a stand-in for C++ default value constructors, since this was written -when the codebase still used C89. - -Note that I prefer to include a space on the inside of the macro parentheses, since -they effectively stand in for curly braces as struct initializers. -*/ - - -MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES]; - -// common font types -// tilenums are set after namesdyn runs - -// emptychar x,y between x,y zoom cursorLeft cursorCenter cursorScale textflags -// tilenum shade_deselected shade_disabled pal pal_selected pal_deselected pal_disabled -MenuFont_t MF_Redfont = { { 5<<16, 15<<16 }, { 0, 0 }, 65536, 20<<16, 110<<16, 65536, TEXT_BIGALPHANUM | TEXT_UPPERCASE, - -1, 10, 0, 0, 0, 0, 1, - 0, 0, 1 }; -MenuFont_t MF_Bluefont = { { 5<<16, 7<<16 }, { 0, 0 }, 65536, 10<<16, 110<<16, 32768, 0, - -1, 10, 0, 0, 10, 10, 16, - 0, 0, 16 }; -MenuFont_t MF_Minifont = { { 4<<16, 5<<16 }, { 1<<16, 1<<16 }, 65536, 10<<16, 110<<16, 32768, 0, - -1, 10, 0, 0, 2, 2, 0, - 0, 0, 16 }; - - -static MenuMenuFormat_t MMF_Top_Main = { { MENU_MARGIN_CENTER<<16, 55<<16, }, -(170<<16) }; -static MenuMenuFormat_t MMF_Top_Episode = { { MENU_MARGIN_CENTER<<16, 48<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_Top_NewGameCustom = { { MENU_MARGIN_CENTER<<16, 48<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_Top_NewGameCustomSub = { { MENU_MARGIN_CENTER<<16, 48<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_Top_Skill = { { MENU_MARGIN_CENTER<<16, 58<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_Top_Options = { { MENU_MARGIN_CENTER<<16, 38<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_Top_Joystick_Network = { { MENU_MARGIN_CENTER<<16, 70<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_BigOptions = { { MENU_MARGIN_WIDE<<16, 38<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_SmallOptions = { { MENU_MARGIN_WIDE<<16, 37<<16, }, 170<<16 }; -static MenuMenuFormat_t MMF_Macros = { { 26<<16, 40<<16, }, 160<<16 }; -static MenuMenuFormat_t MMF_SmallOptionsNarrow = { { MENU_MARGIN_REGULAR<<16, 38<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_KeyboardSetupFuncs = { { 50<<16, 34<<16, }, 151<<16 }; -static MenuMenuFormat_t MMF_MouseJoySetupBtns = { { 76<<16, 34<<16, }, 143<<16 }; -static MenuMenuFormat_t MMF_FuncList = { { 100<<16, 51<<16, }, 152<<16 }; -static MenuMenuFormat_t MMF_ColorCorrect = { { MENU_MARGIN_REGULAR<<16, 86<<16, }, 190<<16 }; -static MenuMenuFormat_t MMF_BigSliders = { { MENU_MARGIN_WIDE<<16, 37<<16, }, 190<<16 }; -static MenuMenuFormat_t MMF_LoadSave = { { 200<<16, 49<<16, }, 145<<16 }; -static MenuMenuFormat_t MMF_NetSetup = { { 36<<16, 38<<16, }, 190<<16 }; -static MenuMenuFormat_t MMF_FileSelectLeft = { { 40<<16, 45<<16, }, 162<<16 }; -static MenuMenuFormat_t MMF_FileSelectRight = { { 164<<16, 45<<16, }, 162<<16 }; - -static MenuEntryFormat_t MEF_Null = { 0, 0, 0 }; -static MenuEntryFormat_t MEF_MainMenu = { 4<<16, 0, 0 }; -static MenuEntryFormat_t MEF_OptionsMenu = { 7<<16, 0, 0 }; -static MenuEntryFormat_t MEF_LeftMenu = { 7<<16, 0, 120<<16 }; -static MenuEntryFormat_t MEF_CenterMenu = { 7<<16, 0, 0 }; -static MenuEntryFormat_t MEF_BigOptions_Apply = { 4<<16, 16<<16, -(260<<16) }; -static MenuEntryFormat_t MEF_BigOptionsRt = { 4<<16, 0, -(260<<16) }; -static MenuEntryFormat_t MEF_BigOptionsRtSections = { 3<<16, 0, -(260<<16) }; -#if defined USE_OPENGL || !defined EDUKE32_ANDROID_MENU -static MenuEntryFormat_t MEF_SmallOptions = { 1<<16, 0, -(260<<16) }; -#endif -static MenuEntryFormat_t MEF_BigCheats = { 3<<16, 0, -(260<<16) }; -static MenuEntryFormat_t MEF_Cheats = { 2<<16, 0, -(260<<16) }; -static MenuEntryFormat_t MEF_PlayerNarrow = { 1<<16, 0, 90<<16 }; -static MenuEntryFormat_t MEF_Macros = { 2<<16, -1, 268<<16 }; -static MenuEntryFormat_t MEF_VideoSetup = { 4<<16, 0, 168<<16 }; -static MenuEntryFormat_t MEF_VideoSetup_Apply = { 4<<16, 16<<16, 168<<16 }; -static MenuEntryFormat_t MEF_KBFuncList = { 3<<16, 0, -(225<<16) }; -static MenuEntryFormat_t MEF_FuncList = { 3<<16, 0, -(170<<16) }; -static MenuEntryFormat_t MEF_ColorCorrect = { 2<<16, 0, -(240<<16) }; -static MenuEntryFormat_t MEF_BigSliders = { 2<<16, 0, -(260<<16) }; -static MenuEntryFormat_t MEF_LoadSave = { 2<<16, -1, 78<<16 }; -static MenuEntryFormat_t MEF_NetSetup = { 4<<16, 0, 112<<16 }; -static MenuEntryFormat_t MEF_NetSetup_Confirm = { 4<<16, 16<<16, 112<<16 }; - -// common menu option sets -#define MAKE_MENUOPTIONSET(optionNames, optionValues, features) { optionNames, optionValues, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, ARRAY_SIZE(optionNames), -1, 0, features } -#define MAKE_MENUOPTIONSETDYN(optionNames, optionValues, numOptions, features) { optionNames, optionValues, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, numOptions, -1, 0, features } -#define MAKE_MENUOPTIONSETNULL { NULL, NULL, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, 0, -1, 0, 0 } - -static char const *MEOSN_OffOn[] = { "Off", "On", }; -static MenuOptionSet_t MEOS_OffOn = MAKE_MENUOPTIONSET( MEOSN_OffOn, NULL, 0x3 ); -static char const *MEOSN_OnOff[] = { "On", "Off", }; -static MenuOptionSet_t MEOS_OnOff = MAKE_MENUOPTIONSET( MEOSN_OnOff, NULL, 0x3 ); -static char const *MEOSN_NoYes[] = { "No", "Yes", }; -static MenuOptionSet_t MEOS_NoYes = MAKE_MENUOPTIONSET( MEOSN_NoYes, NULL, 0x3 ); -static char const *MEOSN_YesNo[] = { "Yes", "No", }; -static MenuOptionSet_t MEOS_YesNo = MAKE_MENUOPTIONSET( MEOSN_YesNo, NULL, 0x3 ); - - -static FString MenuGameFuncs[NUMGAMEFUNCTIONS]; -static char const *MenuGameFuncNone = " -None-"; -static char const *MEOSN_Gamefuncs[NUMGAMEFUNCTIONS+1]; -static int32_t MEOSV_Gamefuncs[NUMGAMEFUNCTIONS+1]; -static MenuOptionSet_t MEOS_Gamefuncs = MAKE_MENUOPTIONSET( MEOSN_Gamefuncs, MEOSV_Gamefuncs, 0x1 ); - - - -/* -MenuEntry_t is passed in arrays of pointers so that the callback function -that is called when an entry is modified or activated can test equality of the current -entry pointer directly against the known ones, instead of relying on an ID number. - -That way, individual menu entries can be ifdef'd out painlessly. -*/ - -static MenuLink_t MEO_NULL = { MENU_NULL, MA_None, }; -static const char* MenuCustom = "Custom"; - -#define MAKE_MENUSTRING(...) { NULL, __VA_ARGS__, } -#define MAKE_MENUOPTION(...) { __VA_ARGS__, -1, } -#define MAKE_MENURANGE(...) { __VA_ARGS__, } -#define MAKE_MENUENTRY(...) { __VA_ARGS__, 0, 0, 0, } - - -#define MAKE_SPACER( EntryName, Height ) \ -static MenuSpacer_t MEO_ ## EntryName = { Height }; - -MAKE_SPACER( Space2, 2<<16 ); // bigoptions -MAKE_SPACER( Space4, 4<<16 ); // usermap, smalloptions, anything else non-top -MAKE_SPACER( Space6, 6<<16 ); // videosetup -MAKE_SPACER( Space8, 8<<16 ); // colcorr, redslide - -static MenuEntry_t ME_Space2_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space2, Spacer ); -static MenuEntry_t ME_Space4_Bluefont = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Null, &MEO_Space4, Spacer ); -static MenuEntry_t ME_Space4_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space4, Spacer ); -#ifndef EDUKE32_SIMPLE_MENU -static MenuEntry_t ME_Space8_Bluefont = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Null, &MEO_Space8, Spacer ); -#endif -static MenuEntry_t ME_Space6_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space6, Spacer ); -static MenuEntry_t ME_Space8_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space8, Spacer ); - -#define MAKE_MENU_TOP_ENTRYLINK( Title, Format, EntryName, LinkID ) \ -static MenuLink_t MEO_ ## EntryName = { LinkID, MA_Advance, };\ -static MenuEntry_t ME_ ## EntryName = MAKE_MENUENTRY( Title, &MF_Redfont, &Format, &MEO_ ## EntryName, Link ) - -static char const s_NewGame[] = "New Game"; -static char const s_SaveGame[] = "Save Game"; -static char const s_LoadGame[] = "Load Game"; -static char const s_Continue[] = "Continue"; -static char const s_Options[] = "Options"; -static char const s_Credits[] = "Credits"; - -MAKE_MENU_TOP_ENTRYLINK( s_NewGame, MEF_MainMenu, MAIN_NEWGAME, MENU_EPISODE ); -#ifdef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK( "Resume Game", MEF_MainMenu, MAIN_RESUMEGAME, MENU_CLOSE ); -#endif -MAKE_MENU_TOP_ENTRYLINK( s_NewGame, MEF_MainMenu, MAIN_NEWGAME_INGAME, MENU_NEWVERIFY ); -static MenuLink_t MEO_MAIN_NEWGAME_NETWORK = { MENU_NETWORK, MA_Advance, }; -MAKE_MENU_TOP_ENTRYLINK( s_SaveGame, MEF_MainMenu, MAIN_SAVEGAME, MENU_SAVE ); -MAKE_MENU_TOP_ENTRYLINK( s_LoadGame, MEF_MainMenu, MAIN_LOADGAME, MENU_LOAD ); -MAKE_MENU_TOP_ENTRYLINK( s_Options, MEF_MainMenu, MAIN_OPTIONS, MENU_OPTIONS ); -#ifdef EDUKE32_STANDALONE -MAKE_MENU_TOP_ENTRYLINK( "Read me!", MEF_MainMenu, MAIN_HELP, MENU_STORY ); -#else -MAKE_MENU_TOP_ENTRYLINK("Help", MEF_MainMenu, MAIN_HELP, MENU_STORY); -#endif -#ifndef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK( s_Credits, MEF_MainMenu, MAIN_CREDITS, MENU_CREDITS ); -#endif -MAKE_MENU_TOP_ENTRYLINK( "End Game", MEF_MainMenu, MAIN_QUITTOTITLE, MENU_QUITTOTITLE ); -MAKE_MENU_TOP_ENTRYLINK( "Quit", MEF_MainMenu, MAIN_QUIT, MENU_QUIT ); -#ifndef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK( "Quit Game", MEF_MainMenu, MAIN_QUITGAME, MENU_QUIT ); -#endif - -static MenuEntry_t *MEL_MAIN[] = { - &ME_MAIN_NEWGAME, - &ME_MAIN_LOADGAME, - &ME_MAIN_OPTIONS, - &ME_MAIN_HELP, -#ifndef EDUKE32_SIMPLE_MENU - &ME_MAIN_CREDITS, -#endif - &ME_MAIN_QUIT, -}; - -static MenuEntry_t *MEL_MAIN_INGAME[] = { -#ifdef EDUKE32_SIMPLE_MENU - &ME_MAIN_RESUMEGAME, -#else - &ME_MAIN_NEWGAME_INGAME, -#endif - &ME_MAIN_SAVEGAME, - &ME_MAIN_LOADGAME, - &ME_MAIN_OPTIONS, - &ME_MAIN_HELP, - &ME_MAIN_QUITTOTITLE, -#ifndef EDUKE32_SIMPLE_MENU - &ME_MAIN_QUITGAME, -#endif -}; - -// Episode and Skill will be dynamically generated after CONs are parsed -static MenuLink_t MEO_EPISODE = { MENU_SKILL, MA_Advance, }; -static MenuLink_t MEO_EPISODE_SHAREWARE = { MENU_BUYDUKE, MA_Advance, }; -static MenuEntry_t ME_EPISODE_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_CenterMenu, &MEO_EPISODE, Link ); -static MenuEntry_t ME_EPISODE[MAXVOLUMES]; -static MenuLink_t MEO_EPISODE_USERMAP = { MENU_USERMAP, MA_Advance, }; -static MenuEntry_t ME_EPISODE_USERMAP = MAKE_MENUENTRY( "User Map", &MF_Redfont, &MEF_CenterMenu, &MEO_EPISODE_USERMAP, Link ); -static MenuEntry_t *MEL_EPISODE[MAXVOLUMES+2]; // +2 for spacer and User Map - -static MenuLink_t MEO_NEWGAMECUSTOM_TEMPLATE = { MENU_NEWGAMECUSTOMSUB, MA_Advance, }; -static MenuLink_t MEO_NEWGAMECUSTOM[MAXMENUGAMEPLAYENTRIES]; -static MenuLink_t MEO_NEWGAMECUSTOMSUB_TEMPLATE = { MENU_SKILL, MA_Advance, }; -static MenuLink_t MEO_NEWGAMECUSTOMSUB[MAXMENUGAMEPLAYENTRIES][MAXMENUGAMEPLAYENTRIES]; -MenuEntry_t ME_NEWGAMECUSTOMENTRIES[MAXMENUGAMEPLAYENTRIES]; -MenuEntry_t ME_NEWGAMECUSTOMSUBENTRIES[MAXMENUGAMEPLAYENTRIES][MAXMENUGAMEPLAYENTRIES]; -static MenuEntry_t *MEL_NEWGAMECUSTOM[MAXMENUGAMEPLAYENTRIES]; -static MenuEntry_t *MEL_NEWGAMECUSTOMSUB[MAXMENUGAMEPLAYENTRIES]; - -static MenuEntry_t ME_SKILL_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_CenterMenu, &MEO_NULL, Link ); -static MenuEntry_t ME_SKILL[MAXSKILLS]; -static MenuEntry_t *MEL_SKILL[MAXSKILLS]; - -static char const *MEOSN_GAMESETUP_AIM_AUTO[] = { "Never", "Always", "Hitscan only", -}; -static int32_t MEOSV_GAMESETUP_AIM_AUTO[] = { 0, 1, 2, -}; - -static MenuOptionSet_t MEOS_GAMESETUP_AIM_AUTO = MAKE_MENUOPTIONSET( MEOSN_GAMESETUP_AIM_AUTO, MEOSV_GAMESETUP_AIM_AUTO, 0x2 ); -static MenuOption_t MEO_GAMESETUP_AIM_AUTO = MAKE_MENUOPTION( &MF_Redfont, &MEOS_GAMESETUP_AIM_AUTO, &cl_autoaim ); -static MenuEntry_t ME_GAMESETUP_AIM_AUTO = MAKE_MENUENTRY( "Auto aim:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_AIM_AUTO, Option ); - -static MenuOption_t MEO_GAMESETUP_ALWAYS_RUN = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &cl_autorun); -static MenuEntry_t ME_GAMESETUP_ALWAYS_RUN = MAKE_MENUENTRY( "Always run:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_ALWAYS_RUN, Option ); - -static char const *MEOSN_GAMESETUP_WEAPSWITCH_PICKUP[] = { "Never", "If new", /*"If favored",*/ }; -static MenuOptionSet_t MEOS_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUOPTIONSET( MEOSN_GAMESETUP_WEAPSWITCH_PICKUP, NULL, 0x2 ); -static MenuOption_t MEO_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUOPTION( &MF_Redfont, &MEOS_GAMESETUP_WEAPSWITCH_PICKUP, NULL ); -static MenuEntry_t ME_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUENTRY( "Equip pickups:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_WEAPSWITCH_PICKUP, Option ); - -static char const *MEOSN_DemoRec[] = { "Off", "Running", }; -static MenuOptionSet_t MEOS_DemoRec = MAKE_MENUOPTIONSET( MEOSN_DemoRec, NULL, 0x3 ); -static MenuOption_t MEO_GAMESETUP_DEMOREC = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &m_recstat ); -static MenuEntry_t ME_GAMESETUP_DEMOREC = MAKE_MENUENTRY( "Record demo:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_DEMOREC, Option ); - -static MenuOption_t MEO_ADULTMODE = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &adult_lockout); -static MenuEntry_t ME_ADULTMODE = MAKE_MENUENTRY( "Parental lock:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_ADULTMODE, Option ); - -#if defined(EDUKE32_ANDROID_MENU) || !defined(EDUKE32_SIMPLE_MENU) -static MenuLink_t MEO_GAMESETUP_CHEATS = { MENU_CHEATS, MA_Advance, }; -static MenuEntry_t ME_GAMESETUP_CHEATS = MAKE_MENUENTRY( "Cheats", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_CHEATS, Link ); - -static MenuEntry_t *MEL_GAMESETUP[] = { - &ME_ADULTMODE, -#if defined STARTUP_SETUP_WINDOW && !defined EDUKE32_SIMPLE_MENU - &ME_GAMESETUP_STARTWIN, -#endif -#ifndef EDUKE32_ANDROID_MENU - &ME_GAMESETUP_DEMOREC, -#endif - &ME_GAMESETUP_CHEATS, -}; -#endif - -#ifndef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK( "Game Setup", MEF_OptionsMenu, OPTIONS_GAMESETUP, MENU_GAMESETUP ); -#endif -MAKE_MENU_TOP_ENTRYLINK( "Sound Setup", MEF_OptionsMenu, OPTIONS_SOUNDSETUP, MENU_SOUND ); -MAKE_MENU_TOP_ENTRYLINK( "Display Setup", MEF_OptionsMenu, OPTIONS_DISPLAYSETUP, MENU_DISPLAYSETUP ); -MAKE_MENU_TOP_ENTRYLINK( "Player Setup", MEF_OptionsMenu, OPTIONS_PLAYERSETUP, MENU_PLAYER ); -#ifndef EDUKE32_ANDROID_MENU -MAKE_MENU_TOP_ENTRYLINK( "Control Setup", MEF_OptionsMenu, OPTIONS_CONTROLS, MENU_CONTROLS ); - -MAKE_MENU_TOP_ENTRYLINK( "Configure Controls", MEF_BigOptionsRtSections, OPTIONS_KEYBOARDSETUP, MENU_KEYBOARDSETUP ); -MAKE_MENU_TOP_ENTRYLINK( "Mouse Setup", MEF_BigOptionsRtSections, OPTIONS_MOUSESETUP, MENU_MOUSESETUP ); -#endif -MAKE_MENU_TOP_ENTRYLINK( "Gamepad Setup", MEF_BigOptionsRtSections, OPTIONS_JOYSTICKSETUP, MENU_JOYSTICKSETUP ); -#ifdef EDUKE32_ANDROID_MENU -MAKE_MENU_TOP_ENTRYLINK( "Touch Setup", MEF_BigOptionsRtSections, OPTIONS_TOUCHSETUP, MENU_TOUCHSETUP ); -#endif -#ifdef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK("Cheats", MEF_OptionsMenu, OPTIONS_CHEATS, MENU_CHEATS); -#endif - -// Zhe menu code lacks flexibility, it can either be hardwired to ints or to CVARs. -// Since CVARs are more important it means that these need to be implemented as CVARs even though they are just temporaries. -// By giving them no name we ensure that they remain outside the CVAR system. -CVAR_UNAMED(Int, newresolution) -CVAR_UNAMED(Int, newrendermode) -CVAR_UNAMED(Int, newfullscreen) -CVAR_UNAMED(Int, newvsync) -CVAR_UNAMED(Int, newborderless) - -enum resflags_t { - RES_FS = 0x1, - RES_WIN = 0x2, -}; - -#define MAXRESOLUTIONSTRINGLENGTH 19 - -typedef struct resolution_t { - int32_t xdim, ydim; - int32_t flags; - int32_t bppmax; - char name[MAXRESOLUTIONSTRINGLENGTH]; -} resolution_t; - -resolution_t resolution[MAXVALIDMODES]; - -static char const *MEOSN_VIDEOSETUP_RESOLUTION[MAXVALIDMODES]; -static MenuOptionSet_t MEOS_VIDEOSETUP_RESOLUTION = MAKE_MENUOPTIONSETDYN( MEOSN_VIDEOSETUP_RESOLUTION, NULL, 0, 0x0 ); -static MenuOption_t MEO_VIDEOSETUP_RESOLUTION = MAKE_MENUOPTION( &MF_Redfont, &MEOS_VIDEOSETUP_RESOLUTION, &newresolution ); -static MenuEntry_t ME_VIDEOSETUP_RESOLUTION = MAKE_MENUENTRY( "Resolution:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_RESOLUTION, Option ); - -#ifdef USE_OPENGL -static char const *MEOSN_VIDEOSETUP_RENDERER[] = { "Classic", "OpenGL", }; -static int32_t MEOSV_VIDEOSETUP_RENDERER[] = { REND_CLASSIC, REND_POLYMOST, }; - -static MenuOptionSet_t MEOS_VIDEOSETUP_RENDERER = MAKE_MENUOPTIONSET( MEOSN_VIDEOSETUP_RENDERER, MEOSV_VIDEOSETUP_RENDERER, 0x2 ); - -static MenuOption_t MEO_VIDEOSETUP_RENDERER = MAKE_MENUOPTION( &MF_Redfont, &MEOS_VIDEOSETUP_RENDERER, &newrendermode ); -static MenuEntry_t ME_VIDEOSETUP_RENDERER = MAKE_MENUENTRY( "Renderer:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_RENDERER, Option ); -#endif - -static MenuOption_t MEO_VIDEOSETUP_FULLSCREEN = MAKE_MENUOPTION( &MF_Redfont, &MEOS_YesNo, &newfullscreen ); -static MenuEntry_t ME_VIDEOSETUP_FULLSCREEN = MAKE_MENUENTRY( "Windowed:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_FULLSCREEN, Option ); - -static char const *MEOSN_VIDEOSETUP_BORDERLESS [] = { "No", "Yes", "Auto", }; -static int32_t MEOSV_VIDEOSETUP_BORDERLESS [] = { 0, 1, 2, }; -static MenuOptionSet_t MEOS_VIDEOSETUP_BORDERLESS = MAKE_MENUOPTIONSET(MEOSN_VIDEOSETUP_BORDERLESS, MEOSV_VIDEOSETUP_BORDERLESS, 0x2); -static MenuOption_t MEO_VIDEOSETUP_BORDERLESS = MAKE_MENUOPTION(&MF_Redfont, &MEOS_VIDEOSETUP_BORDERLESS, &newborderless); -static MenuEntry_t ME_VIDEOSETUP_BORDERLESS = MAKE_MENUENTRY("Borderless:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_BORDERLESS, Option); - -static char const *MEOSN_VIDEOSETUP_VSYNC [] = { "Adaptive", "Off", "On", }; -static int32_t MEOSV_VIDEOSETUP_VSYNC [] = { -1, 0, 1, }; -static MenuOptionSet_t MEOS_VIDEOSETUP_VSYNC = MAKE_MENUOPTIONSET(MEOSN_VIDEOSETUP_VSYNC, MEOSV_VIDEOSETUP_VSYNC, 0x2); -static MenuOption_t MEO_VIDEOSETUP_VSYNC = MAKE_MENUOPTION(&MF_Redfont, &MEOS_VIDEOSETUP_VSYNC, &newvsync); -static MenuEntry_t ME_VIDEOSETUP_VSYNC = MAKE_MENUENTRY("VSync:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_VSYNC, Option); - - - -//static char const *MEOSN_VIDEOSETUP_FRAMELIMIT [] = { "None", "30 fps", "60 fps", "75 fps", "100 fps", "120 fps", "144 fps", "165 fps", "240 fps" }; - -static MenuEntry_t ME_VIDEOSETUP_APPLY = MAKE_MENUENTRY( "Apply Changes", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_NULL, Link ); - - -static MenuLink_t MEO_DISPLAYSETUP_COLORCORR = { MENU_COLCORR, MA_Advance, }; -static MenuEntry_t ME_DISPLAYSETUP_COLORCORR = MAKE_MENUENTRY( "Color Correction", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_COLORCORR, Link ); - - -#ifndef EDUKE32_ANDROID_MENU -static MenuOption_t MEO_DISPLAYSETUP_ASPECTRATIO = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &r_usenewaspect); -static MenuEntry_t ME_DISPLAYSETUP_ASPECTRATIO = MAKE_MENUENTRY( "Widescreen:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ASPECTRATIO, Option ); -#endif - -static MenuOption_t MEO_DISPLAYSETUP_VOXELS = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &r_voxels); -static MenuEntry_t ME_DISPLAYSETUP_VOXELS = MAKE_MENUENTRY( "Voxels:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_VOXELS, Option ); - -static MenuRangeInt32_t MEO_DISPLAYSETUP_FOV = MAKE_MENURANGE( &r_fov, &MF_Redfont, 70, 120, 0, 11, 1 ); -static MenuEntry_t ME_DISPLAYSETUP_FOV = MAKE_MENUENTRY( "FOV:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_FOV, RangeInt32 ); - - -#ifdef USE_OPENGL -static char const *MEOSN_DISPLAYSETUP_TEXFILTER[] = { "Classic", "Filtered" }; -static int32_t MEOSV_DISPLAYSETUP_TEXFILTER[] = { TEXFILTER_OFF, TEXFILTER_ON }; -static MenuOptionSet_t MEOS_DISPLAYSETUP_TEXFILTER = MAKE_MENUOPTIONSET( MEOSN_DISPLAYSETUP_TEXFILTER, MEOSV_DISPLAYSETUP_TEXFILTER, 0x2 ); -static MenuOption_t MEO_DISPLAYSETUP_TEXFILTER = MAKE_MENUOPTION( &MF_Redfont, &MEOS_DISPLAYSETUP_TEXFILTER, &hw_texfilter ); -static MenuEntry_t ME_DISPLAYSETUP_TEXFILTER = MAKE_MENUENTRY( "Texture Mode:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_TEXFILTER, Option ); - -static char const *MEOSN_DISPLAYSETUP_ANISOTROPY[] = { "Max", "None", "2x", "4x", "8x", "16x", }; -static int32_t MEOSV_DISPLAYSETUP_ANISOTROPY[] = { 0, 1, 2, 4, 8, 16, }; -static MenuOptionSet_t MEOS_DISPLAYSETUP_ANISOTROPY = MAKE_MENUOPTIONSET( MEOSN_DISPLAYSETUP_ANISOTROPY, MEOSV_DISPLAYSETUP_ANISOTROPY, 0x0 ); -static MenuOption_t MEO_DISPLAYSETUP_ANISOTROPY = MAKE_MENUOPTION(&MF_Redfont, &MEOS_DISPLAYSETUP_ANISOTROPY, &hw_anisotropy); -static MenuEntry_t ME_DISPLAYSETUP_ANISOTROPY = MAKE_MENUENTRY( "Anisotropy:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ANISOTROPY, Option ); - -#endif - -static char const s_Scale[] = "Scale:"; - -static MenuOption_t MEO_SCREENSETUP_CROSSHAIR = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &cl_crosshair); -static MenuEntry_t ME_SCREENSETUP_CROSSHAIR = MAKE_MENUENTRY( "Crosshair:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_CROSSHAIR, Option ); -static MenuRangeInt32_t MEO_SCREENSETUP_CROSSHAIRSIZE = MAKE_MENURANGE( &cl_crosshairscale, &MF_Redfont, 25, 100, 0, 16, 2 ); -static MenuEntry_t ME_SCREENSETUP_CROSSHAIRSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_CROSSHAIRSIZE, RangeInt32 ); - -static MenuRangeInt32_t MEO_SCREENSETUP_SCREENSIZE = MAKE_MENURANGE( &hud_size, &MF_Redfont, 0, 11, 0, 1, EnforceIntervals ); -static MenuOption_t MEO_SCREENSETUP_SCREENSIZE_TWO = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &hud_size ); -static MenuEntry_t ME_SCREENSETUP_SCREENSIZE = MAKE_MENUENTRY( "Status bar:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_SCREENSIZE, RangeInt32 ); -static MenuRangeInt32_t MEO_SCREENSETUP_TEXTSIZE = MAKE_MENURANGE( &hud_textscale, &MF_Redfont, 100, 400, 0, 16, 2 ); -static MenuEntry_t ME_SCREENSETUP_TEXTSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_TEXTSIZE, RangeInt32 ); -static MenuOption_t MEO_SCREENSETUP_LEVELSTATS = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &hud_stats); -static MenuEntry_t ME_SCREENSETUP_LEVELSTATS = MAKE_MENUENTRY( "Level stats:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_LEVELSTATS, Option ); - - -static MenuOption_t MEO_SCREENSETUP_SHOWPICKUPMESSAGES = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &hud_messages); -static MenuEntry_t ME_SCREENSETUP_SHOWPICKUPMESSAGES = MAKE_MENUENTRY( "Game messages:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_SHOWPICKUPMESSAGES, Option ); - -static MenuRangeInt32_t MEO_SCREENSETUP_SBARSIZE = MAKE_MENURANGE( &hud_scale, &MF_Redfont, 50, 100, 0, 10, 2 ); -static MenuEntry_t ME_SCREENSETUP_SBARSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_SBARSIZE, RangeInt32 ); - - -static MenuLink_t MEO_DISPLAYSETUP_SCREENSETUP = { MENU_SCREENSETUP, MA_Advance, }; -static MenuEntry_t ME_DISPLAYSETUP_SCREENSETUP = MAKE_MENUENTRY( "HUD setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_SCREENSETUP, Link ); - - -#ifdef USE_OPENGL -static MenuLink_t MEO_DISPLAYSETUP_ADVANCED_GL_POLYMOST = { MENU_POLYMOST, MA_Advance, }; -static MenuEntry_t ME_DISPLAYSETUP_ADVANCED_GL_POLYMOST = MAKE_MENUENTRY( "Polymost setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ADVANCED_GL_POLYMOST, Link ); -#endif - -#ifndef EDUKE32_ANDROID_MENU -static MenuLink_t MEO_DISPLAYSETUP_VIDEOSETUP = { MENU_VIDEOSETUP, MA_Advance, }; -static MenuEntry_t ME_DISPLAYSETUP_VIDEOSETUP = MAKE_MENUENTRY( "Video mode", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_VIDEOSETUP, Link ); -#endif - - -static MenuLink_t MEO_ENTERCHEAT = { MENU_CHEATENTRY, MA_None, }; -static MenuEntry_t ME_ENTERCHEAT = MAKE_MENUENTRY( "Enter Cheat Code", &MF_Redfont, &MEF_BigCheats, &MEO_ENTERCHEAT, Link ); - -static MenuLink_t MEO_CHEAT_WARP = { MENU_CHEAT_WARP, MA_None, }; -static MenuLink_t MEO_CHEAT_SKILL = { MENU_CHEAT_SKILL, MA_None, }; -// KEEPINSYNC cheats.h: enum CheatCodeFunctions -// KEEPINSYNC cheats.cpp: uint8_t CheatFunctionIDs[] -#define MAKE_MENUCHEAT( Name ) MAKE_MENUENTRY( Name, &MF_Bluefont, &MEF_Cheats, &MEO_NULL, Link ) -static MenuEntry_t ME_CheatCodes[] = { - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_CASHMAN] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_CORNHOLIO] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_STUFF] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_WEAPONS] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_ITEMS] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_INVENTORY] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_KEYS] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_HYPER] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_VIEW] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_SHOWMAP] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_UNLOCK] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_CLIP] ), - MAKE_MENUENTRY( CheatDescriptions[CHEAT_SCOTTY], &MF_Bluefont, &MEF_Cheats, &MEO_CHEAT_WARP, Link ), - MAKE_MENUENTRY( CheatDescriptions[CHEAT_SKILL], &MF_Bluefont, &MEF_Cheats, &MEO_CHEAT_SKILL, Link ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_MONSTERS] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_RATE] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_BETA] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_TODD] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_ALLEN] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_COORDS] ), - MAKE_MENUCHEAT( CheatDescriptions[CHEAT_DEBUG] ), -}; - -static MenuEntry_t *MEL_OPTIONS[] = { -#ifndef EDUKE32_SIMPLE_MENU - &ME_OPTIONS_GAMESETUP, -#endif - &ME_OPTIONS_DISPLAYSETUP, - &ME_OPTIONS_SOUNDSETUP, -#ifndef EDUKE32_ANDROID_MENU -#ifndef EDUKE32_SIMPLE_MENU - &ME_OPTIONS_PLAYERSETUP, -#endif - &ME_OPTIONS_CONTROLS, -#else - &ME_OPTIONS_TOUCHSETUP, -#endif -#ifdef EDUKE32_SIMPLE_MENU - &ME_GAMESETUP_SAVESETUP, - &ME_OPTIONS_CHEATS -#endif -}; - -static MenuEntry_t *MEL_CONTROLS[] = { -#ifndef EDUKE32_ANDROID_MENU - &ME_OPTIONS_KEYBOARDSETUP, - &ME_OPTIONS_MOUSESETUP, - &ME_OPTIONS_JOYSTICKSETUP, -#else - &ME_OPTIONS_TOUCHSETUP, -#endif - &ME_Space6_Redfont, - &ME_GAMESETUP_AIM_AUTO, - &ME_GAMESETUP_ALWAYS_RUN, - &ME_GAMESETUP_WEAPSWITCH_PICKUP, -#ifdef EDUKE32_ANDROID_MENU - &ME_GAMESETUP_QUICKSWITCH, - &ME_GAMESETUP_CROUCHLOCK, -#endif -}; - -static MenuEntry_t *MEL_CHEATS[ARRAY_SIZE(ME_CheatCodes)+1] = { - &ME_ENTERCHEAT, -}; - -static MenuEntry_t *MEL_VIDEOSETUP[] = { - &ME_VIDEOSETUP_RESOLUTION, -#ifdef USE_OPENGL - &ME_VIDEOSETUP_RENDERER, -#endif - &ME_VIDEOSETUP_FULLSCREEN, - &ME_VIDEOSETUP_BORDERLESS, - &ME_VIDEOSETUP_VSYNC, - &ME_Space4_Redfont, - &ME_VIDEOSETUP_APPLY, -}; -static MenuEntry_t *MEL_DISPLAYSETUP[] = { - &ME_DISPLAYSETUP_SCREENSETUP, - &ME_DISPLAYSETUP_COLORCORR, -#ifndef EDUKE32_ANDROID_MENU - &ME_DISPLAYSETUP_VIDEOSETUP, - &ME_DISPLAYSETUP_ASPECTRATIO, - &ME_DISPLAYSETUP_VOXELS, - &ME_DISPLAYSETUP_FOV, -#endif -}; - -#ifdef USE_OPENGL -static MenuEntry_t *MEL_DISPLAYSETUP_GL[] = { - &ME_DISPLAYSETUP_SCREENSETUP, - &ME_DISPLAYSETUP_COLORCORR, - &ME_DISPLAYSETUP_VIDEOSETUP, - &ME_DISPLAYSETUP_ASPECTRATIO, - &ME_DISPLAYSETUP_VOXELS, - &ME_DISPLAYSETUP_FOV, - &ME_DISPLAYSETUP_TEXFILTER, - &ME_DISPLAYSETUP_ANISOTROPY, - &ME_DISPLAYSETUP_ADVANCED_GL_POLYMOST, -#endif -}; - - - -static char const MenuKeyNone[] = " -"; -static char const *MEOSN_Keys[NUMKEYS]; - -static MenuCustom2Col_t MEO_KEYBOARDSETUPFUNCS_TEMPLATE = { 0, &MF_Minifont, NUMKEYS, 54<<16, 0 }; -static MenuCustom2Col_t MEO_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS]; -static MenuEntry_t ME_KEYBOARDSETUPFUNCS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_KBFuncList, &MEO_KEYBOARDSETUPFUNCS_TEMPLATE, Custom2Col ); -static MenuEntry_t ME_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS]; -static MenuEntry_t *MEL_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS]; - -static MenuLink_t MEO_KEYBOARDSETUP_KEYS = { MENU_KEYBOARDKEYS, MA_Advance, }; -static MenuEntry_t ME_KEYBOARDSETUP_KEYS = MAKE_MENUENTRY( "Edit Configuration", &MF_Redfont, &MEF_CenterMenu, &MEO_KEYBOARDSETUP_KEYS, Link ); -static MenuLink_t MEO_KEYBOARDSETUP_RESET = { MENU_KEYSRESETVERIFY, MA_None, }; -static MenuEntry_t ME_KEYBOARDSETUP_RESET = MAKE_MENUENTRY( "Reset To Defaults", &MF_Redfont, &MEF_CenterMenu, &MEO_KEYBOARDSETUP_RESET, Link ); -static MenuLink_t MEO_KEYBOARDSETUP_RESETCLASSIC = { MENU_KEYSCLASSICVERIFY, MA_None, }; -static MenuEntry_t ME_KEYBOARDSETUP_RESETCLASSIC = MAKE_MENUENTRY( "Reset To Classic", &MF_Redfont, &MEF_CenterMenu, &MEO_KEYBOARDSETUP_RESETCLASSIC, Link ); - -static MenuEntry_t *MEL_KEYBOARDSETUP[] = { - &ME_KEYBOARDSETUP_KEYS, - &ME_KEYBOARDSETUP_RESET, - &ME_KEYBOARDSETUP_RESETCLASSIC, -}; - - -// There is no better way to do this than manually. - -#define MENUMOUSEFUNCTIONS 12 - -static char const *MenuMouseNames[MENUMOUSEFUNCTIONS] = { - "Button 1", - "Double Button 1", - "Button 2", - "Double Button 2", - "Button 3", - "Double Button 3", - - "Wheel Up", - "Wheel Down", - - "Button 4", - "Double Button 4", - "Button 5", - "Double Button 5", -}; -static int32_t MenuMouseDataIndex[MENUMOUSEFUNCTIONS][2] = { - { 0, 0, }, - { 0, 1, }, - { 1, 0, }, - { 1, 1, }, - { 2, 0, }, - { 2, 1, }, - - // note the mouse wheel - { 4, 0, }, - { 5, 0, }, - - { 3, 0, }, - { 3, 1, }, - { 6, 0, }, - { 6, 1, }, -}; - -static MenuOption_t MEO_MOUSEJOYSETUPBTNS_TEMPLATE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL ); -static MenuOption_t MEO_MOUSESETUPBTNS[MENUMOUSEFUNCTIONS]; -static MenuEntry_t ME_MOUSEJOYSETUPBTNS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_FuncList, NULL, Option ); - -static MenuRangeFloat_t MEO_MOUSESETUP_SENSITIVITY = MAKE_MENURANGE( &in_mousesensitivity, &MF_Redfont, .5f, 16.f, 0.f, 32, 1 ); -static MenuEntry_t ME_MOUSESETUP_SENSITIVITY = MAKE_MENUENTRY( "Sensitivity:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_SENSITIVITY, RangeFloat ); - -#ifndef EDUKE32_SIMPLE_MENU -static char const *MEOSN_MOUSESETUP_AIM_TYPE [] = { "Toggle", "Hold" }; -static MenuOptionSet_t MEOS_MOUSESETUP_AIM_TYPE = MAKE_MENUOPTIONSET(MEOSN_MOUSESETUP_AIM_TYPE, NULL, 0x2); -static MenuOption_t MEO_MOUSESETUP_MOUSEAIMINGTYPE = MAKE_MENUOPTION(&MF_Redfont, &MEOS_MOUSESETUP_AIM_TYPE, &in_aimmode); -static MenuEntry_t ME_MOUSESETUP_MOUSEAIMINGTYPE = MAKE_MENUENTRY("Aiming type:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_MOUSEAIMINGTYPE, Option); -static MenuOption_t MEO_MOUSESETUP_MOUSEAIMING = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &in_mousemode ); -static MenuEntry_t ME_MOUSESETUP_MOUSEAIMING = MAKE_MENUENTRY( "Vertical aiming:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_MOUSEAIMING, Option ); -#endif -static MenuOption_t MEO_MOUSESETUP_INVERT = MAKE_MENUOPTION( &MF_Redfont, &MEOS_YesNo, &in_mouseflip ); -static MenuEntry_t ME_MOUSESETUP_INVERT = MAKE_MENUENTRY( "Invert aiming:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_INVERT, Option ); -static MenuOption_t MEO_MOUSESETUP_SMOOTH = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &in_mousesmoothing ); -static MenuEntry_t ME_MOUSESETUP_SMOOTH = MAKE_MENUENTRY( "Filter input:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_SMOOTH, Option ); -#ifndef EDUKE32_SIMPLE_MENU -static MenuLink_t MEO_MOUSESETUP_ADVANCED = { MENU_MOUSEADVANCED, MA_Advance, }; -static MenuEntry_t ME_MOUSESETUP_ADVANCED = MAKE_MENUENTRY( "Advanced setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_ADVANCED, Link ); -#endif -static MenuRangeInt32_t MEO_MOUSEADVANCED_SCALEX = MAKE_MENURANGE(&in_mousescalex, &MF_Redfont, -262144, 262144, 65536, 161, 3); -static MenuEntry_t ME_MOUSEADVANCED_SCALEX = MAKE_MENUENTRY("X-Scale:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSEADVANCED_SCALEX, RangeInt32); -static MenuRangeInt32_t MEO_MOUSEADVANCED_SCALEY = MAKE_MENURANGE(&in_mousescaley, &MF_Redfont, -262144, 262144, 65536, 161, 3); -static MenuEntry_t ME_MOUSEADVANCED_SCALEY = MAKE_MENUENTRY("Y-Scale:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSEADVANCED_SCALEY, RangeInt32); - -static MenuEntry_t *MEL_MOUSESETUP[] = { - &ME_MOUSESETUP_SENSITIVITY, -#ifdef EDUKE32_SIMPLE_MENU - &ME_MOUSEADVANCED_SCALEX, - &ME_MOUSEADVANCED_SCALEY, -#endif - &ME_Space2_Redfont, - &ME_MOUSESETUP_INVERT, - &ME_MOUSESETUP_SMOOTH, -#ifndef EDUKE32_SIMPLE_MENU - &ME_MOUSESETUP_MOUSEAIMINGTYPE, - &ME_MOUSESETUP_MOUSEAIMING, - &ME_MOUSESETUP_ADVANCED, -#endif -}; - -#ifdef EDUKE32_ANDROID_MENU -static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_MOVE = MAKE_MENURANGE(&droidinput.forward_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals); -static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_MOVE = MAKE_MENUENTRY("Running:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_MOVE, RangeFloat); - -static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_STRAFE = MAKE_MENURANGE(&droidinput.strafe_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals); -static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_STRAFE = MAKE_MENUENTRY("Strafing:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_STRAFE, RangeFloat); - -static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_LOOK = MAKE_MENURANGE(&droidinput.pitch_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals); -static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_LOOK = MAKE_MENUENTRY("Looking:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_LOOK, RangeFloat); - -static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_TURN = MAKE_MENURANGE(&droidinput.yaw_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals); -static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_TURN = MAKE_MENUENTRY("Turning:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_TURN, RangeFloat); - -static MenuOption_t MEO_TOUCHSETUP_INVERT = MAKE_MENUOPTION(&MF_Redfont, &MEOS_NoYes, &droidinput.invertLook); -static MenuEntry_t ME_TOUCHSETUP_INVERT = MAKE_MENUENTRY("Invert look:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_INVERT, Option); - -MAKE_MENU_TOP_ENTRYLINK("Sensitivity", MEF_CenterMenu, TOUCHSENS, MENU_TOUCHSENS); -MAKE_MENU_TOP_ENTRYLINK("Button Setup", MEF_CenterMenu, TOUCHBUTTONS, MENU_TOUCHBUTTONS); - -static MenuEntry_t *MEL_TOUCHSETUP [] = { - &ME_TOUCHSENS, - &ME_TOUCHBUTTONS, -}; - -static MenuEntry_t *MEL_TOUCHSENS [] = { - &ME_TOUCHSETUP_SENSITIVITY_MOVE, - &ME_TOUCHSETUP_SENSITIVITY_STRAFE, - &ME_TOUCHSETUP_SENSITIVITY_LOOK, - &ME_TOUCHSETUP_SENSITIVITY_TURN, - &ME_Space2_Redfont, - &ME_TOUCHSETUP_INVERT, -}; -#endif - -static MenuOption_t MEO_JOYSTICK_ENABLE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &in_joystick ); -static MenuEntry_t ME_JOYSTICK_ENABLE = MAKE_MENUENTRY( "Enable Gamepad:", &MF_Redfont, &MEF_BigOptionsRtSections, &MEO_JOYSTICK_ENABLE, Option ); - -MAKE_MENU_TOP_ENTRYLINK( "Edit Buttons", MEF_BigOptionsRtSections, JOYSTICK_EDITBUTTONS, MENU_JOYSTICKBTNS ); -MAKE_MENU_TOP_ENTRYLINK( "Edit Axes", MEF_BigOptionsRtSections, JOYSTICK_EDITAXES, MENU_JOYSTICKAXES ); - -static MenuLink_t MEO_JOYSTICK_DEFAULTS_STANDARD = { MENU_JOYSTANDARDVERIFY, MA_None, }; -static MenuEntry_t ME_JOYSTICK_DEFAULTS_STANDARD = MAKE_MENUENTRY( "Use Standard Layout", &MF_Redfont, &MEF_BigOptionsRtSections, &MEO_JOYSTICK_DEFAULTS_STANDARD, Link ); -static MenuLink_t MEO_JOYSTICK_DEFAULTS_PRO = { MENU_JOYPROVERIFY, MA_None, }; -static MenuEntry_t ME_JOYSTICK_DEFAULTS_PRO = MAKE_MENUENTRY( "Use Pro Layout", &MF_Redfont, &MEF_BigOptionsRtSections, &MEO_JOYSTICK_DEFAULTS_PRO, Link ); -static MenuLink_t MEO_JOYSTICK_DEFAULTS_CLEAR = { MENU_JOYCLEARVERIFY, MA_None, }; -static MenuEntry_t ME_JOYSTICK_DEFAULTS_CLEAR = MAKE_MENUENTRY( "Clear All Settings", &MF_Redfont, &MEF_BigOptionsRtSections, &MEO_JOYSTICK_DEFAULTS_CLEAR, Link ); - -static MenuEntry_t *MEL_JOYSTICKSETUP[] = { - &ME_JOYSTICK_ENABLE, - &ME_Space6_Redfont, - &ME_JOYSTICK_EDITBUTTONS, - &ME_JOYSTICK_EDITAXES, - &ME_Space6_Redfont, - &ME_JOYSTICK_DEFAULTS_STANDARD, - &ME_JOYSTICK_DEFAULTS_PRO, - &ME_JOYSTICK_DEFAULTS_CLEAR, -}; - -#define MAXJOYBUTTONSTRINGLENGTH 32 - -static char MenuJoystickNames[MAXJOYBUTTONSANDHATS*2][MAXJOYBUTTONSTRINGLENGTH]; - -static MenuOption_t MEO_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2]; -static MenuEntry_t ME_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2]; -static MenuEntry_t *MEL_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2]; - -static MenuLink_t MEO_JOYSTICKAXES = { MENU_JOYSTICKAXIS, MA_Advance, }; -static MenuEntry_t ME_JOYSTICKAXES_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXES, Link ); -static MenuEntry_t ME_JOYSTICKAXES[MAXJOYAXES]; -static char MenuJoystickAxes[MAXJOYAXES][MAXJOYBUTTONSTRINGLENGTH]; - -static MenuEntry_t *MEL_JOYSTICKAXES[MAXJOYAXES]; - -static MenuEntry_t *MEL_MOUSEADVANCED[] = { - &ME_MOUSEADVANCED_SCALEX, - &ME_MOUSEADVANCED_SCALEY, -}; - -static const char *MenuJoystickHatDirections[] = { "Up", "Right", "Down", "Left", }; - -static char const *MEOSN_JOYSTICKAXIS_ANALOG[] = { " -None-", "Turning", "Strafing", "Looking", "Moving", }; -static int32_t MEOSV_JOYSTICKAXIS_ANALOG[] = { -1, analog_turning, analog_strafing, analog_lookingupanddown, analog_moving, }; -static MenuOptionSet_t MEOS_JOYSTICKAXIS_ANALOG = MAKE_MENUOPTIONSET( MEOSN_JOYSTICKAXIS_ANALOG, MEOSV_JOYSTICKAXIS_ANALOG, 0x0 ); -static MenuOption_t MEO_JOYSTICKAXIS_ANALOG = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_JOYSTICKAXIS_ANALOG, NULL ); -static MenuEntry_t ME_JOYSTICKAXIS_ANALOG = MAKE_MENUENTRY( "Analog", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_ANALOG, Option ); -static MenuRangeInt32_t MEO_JOYSTICKAXIS_SCALE = MAKE_MENURANGE( NULL, &MF_Bluefont, -262144, 262144, 65536, 161, 3 ); -static MenuEntry_t ME_JOYSTICKAXIS_SCALE = MAKE_MENUENTRY( "Scale", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_SCALE, RangeInt32 ); -static MenuOption_t MEO_JOYSTICKAXIS_INVERT = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, NULL ); -static MenuEntry_t ME_JOYSTICKAXIS_INVERT = MAKE_MENUENTRY( "Invert", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_INVERT, Option ); -static MenuRangeInt32_t MEO_JOYSTICKAXIS_DEAD = MAKE_MENURANGE( NULL, &MF_Bluefont, 0, 10000, 0, 101, 2 ); -static MenuEntry_t ME_JOYSTICKAXIS_DEAD = MAKE_MENUENTRY( "Dead Zone", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DEAD, RangeInt32 ); -static MenuRangeInt32_t MEO_JOYSTICKAXIS_SATU = MAKE_MENURANGE( NULL, &MF_Bluefont, 0, 10000, 0, 101, 2 ); -static MenuEntry_t ME_JOYSTICKAXIS_SATU = MAKE_MENUENTRY( "Saturation", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_SATU, RangeInt32 ); - -static MenuOption_t MEO_JOYSTICKAXIS_DIGITALNEGATIVE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL ); -static MenuEntry_t ME_JOYSTICKAXIS_DIGITALNEGATIVE = MAKE_MENUENTRY( "Digital -", &MF_Bluefont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DIGITALNEGATIVE, Option ); -static MenuOption_t MEO_JOYSTICKAXIS_DIGITALPOSITIVE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL ); -static MenuEntry_t ME_JOYSTICKAXIS_DIGITALPOSITIVE = MAKE_MENUENTRY( "Digital +", &MF_Bluefont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DIGITALPOSITIVE, Option ); - -static MenuEntry_t *MEL_JOYSTICKAXIS[] = { - &ME_JOYSTICKAXIS_ANALOG, - &ME_JOYSTICKAXIS_SCALE, - &ME_JOYSTICKAXIS_INVERT, - &ME_JOYSTICKAXIS_DEAD, - &ME_JOYSTICKAXIS_SATU, - &ME_Space8_Redfont, - &ME_JOYSTICKAXIS_DIGITALNEGATIVE, - &ME_JOYSTICKAXIS_DIGITALPOSITIVE, -}; - -static MenuEntry_t *MEL_INTERNAL_JOYSTICKAXIS_DIGITAL[] = { - &ME_JOYSTICKAXIS_DIGITALNEGATIVE, - &ME_JOYSTICKAXIS_DIGITALPOSITIVE, -}; - -#ifdef USE_OPENGL -static MenuOption_t MEO_RENDERERSETUP_HIGHTILE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_hightile ); -static MenuEntry_t ME_RENDERERSETUP_HIGHTILE = MAKE_MENUENTRY( "True color textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_HIGHTILE, Option ); - - -static MenuOption_t MEO_RENDERERSETUP_PRECACHE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &r_precache ); -static MenuEntry_t ME_RENDERERSETUP_PRECACHE = MAKE_MENUENTRY( "Pre-load map textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_PRECACHE, Option ); -# ifndef EDUKE32_GLES -static char const *MEOSN_RENDERERSETUP_TEXCACHE[] = { "Off", "On", "Compr.", }; -static MenuOptionSet_t MEOS_RENDERERSETUP_TEXCACHE = MAKE_MENUOPTIONSET( MEOSN_RENDERERSETUP_TEXCACHE, NULL, 0x2 ); -# endif -# ifdef USE_GLEXT -static MenuOption_t MEO_RENDERERSETUP_DETAILTEX = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_detailmapping ); -static MenuEntry_t ME_RENDERERSETUP_DETAILTEX = MAKE_MENUENTRY( "Detail textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_DETAILTEX, Option ); -static MenuOption_t MEO_RENDERERSETUP_GLOWTEX = MAKE_MENUOPTION(&MF_Bluefont, &MEOS_NoYes, &hw_glowmapping); -static MenuEntry_t ME_RENDERERSETUP_GLOWTEX = MAKE_MENUENTRY("Glow textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_GLOWTEX, Option); -# endif -static MenuOption_t MEO_RENDERERSETUP_MODELS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_models ); -static MenuEntry_t ME_RENDERERSETUP_MODELS = MAKE_MENUENTRY( "3D models:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_MODELS, Option ); -#endif - - -#ifdef USE_OPENGL -static MenuEntry_t *MEL_RENDERERSETUP_POLYMOST[] = { - &ME_RENDERERSETUP_HIGHTILE, - &ME_RENDERERSETUP_PRECACHE, -# ifdef USE_GLEXT - &ME_RENDERERSETUP_DETAILTEX, - &ME_RENDERERSETUP_GLOWTEX, -# endif - &ME_Space4_Bluefont, - &ME_RENDERERSETUP_MODELS, -}; - -#endif - -static MenuRangeFloat_t MEO_COLCORR_GAMMA = MAKE_MENURANGE( &vid_gamma, &MF_Bluefont, 0.3f, 4.f, 0.f, 75, 1 ); -static MenuEntry_t ME_COLCORR_GAMMA = MAKE_MENUENTRY( "Gamma:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_GAMMA, RangeFloat ); -static MenuRangeFloat_t MEO_COLCORR_CONTRAST = MAKE_MENURANGE( &vid_contrast, &MF_Bluefont, 0.1f, 2.7f, 0.f, 53, 1 ); -static MenuEntry_t ME_COLCORR_CONTRAST = MAKE_MENUENTRY( "Contrast:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_CONTRAST, RangeFloat ); -static MenuRangeFloat_t MEO_COLCORR_BRIGHTNESS = MAKE_MENURANGE( &vid_brightness, &MF_Bluefont, -0.8f, 0.8f, 0.f, 33, 1 ); -static MenuEntry_t ME_COLCORR_BRIGHTNESS = MAKE_MENUENTRY( "Brightness:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_BRIGHTNESS, RangeFloat ); -static MenuLink_t MEO_COLCORR_RESET = { MENU_COLCORRRESETVERIFY, MA_None, }; -static MenuEntry_t ME_COLCORR_RESET = MAKE_MENUENTRY( "Reset To Defaults", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_RESET, Link ); -#ifdef EDUKE32_ANDROID_MENU -#define MINVIS 1.f -#else -#define MINVIS 0.125f -#endif -#ifndef EDUKE32_SIMPLE_MENU -static MenuRangeFloat_t MEO_COLCORR_AMBIENT = MAKE_MENURANGE( &r_ambientlight, &MF_Bluefont, MINVIS, 4.f, 0.f, 32, 1 ); -static MenuEntry_t ME_COLCORR_AMBIENT = MAKE_MENUENTRY( "Visibility:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_AMBIENT, RangeFloat ); -#endif -static MenuEntry_t *MEL_COLCORR[] = { - &ME_COLCORR_GAMMA, -#ifndef EDUKE32_ANDROID_MENU - &ME_COLCORR_CONTRAST, - &ME_COLCORR_BRIGHTNESS, -#endif -#ifndef EDUKE32_SIMPLE_MENU - &ME_COLCORR_AMBIENT, -#endif - &ME_Space8_Redfont, - &ME_COLCORR_RESET, -}; - -static MenuEntry_t *MEL_SCREENSETUP[] = { -#ifdef EDUKE32_ANDROID_MENU - &ME_SCREENSETUP_STATUSBARONTOP, -#endif - &ME_SCREENSETUP_SCREENSIZE, - &ME_SCREENSETUP_SBARSIZE, - - &ME_SCREENSETUP_CROSSHAIR, - &ME_SCREENSETUP_CROSSHAIRSIZE, - - &ME_SCREENSETUP_LEVELSTATS, - &ME_SCREENSETUP_TEXTSIZE, - - &ME_SCREENSETUP_SHOWPICKUPMESSAGES, -}; - -// Save and load will be filled in before every viewing of the save/load screen. -static MenuLink_t MEO_LOAD = { MENU_LOADVERIFY, MA_None, }; -static MenuEntry_t ME_LOAD_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, &MEO_LOAD, Link ); -static MenuEntry_t ME_LOAD_EMPTY = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, nullptr, Dummy ); -static MenuEntry_t *ME_LOAD; -static MenuEntry_t **MEL_LOAD; - -static char const s_NewSaveGame[] = "(New Save Game)"; -static MenuString_t MEO_SAVE_TEMPLATE = MAKE_MENUSTRING( NULL, &MF_Minifont, MAXSAVEGAMENAME, 0 ); -static MenuString_t MEO_SAVE_NEW = MAKE_MENUSTRING( NULL, &MF_Minifont, MAXSAVEGAMENAME, 0 ); -static MenuString_t *MEO_SAVE; -static MenuEntry_t ME_SAVE_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, &MEO_SAVE_TEMPLATE, String ); -static MenuEntry_t ME_SAVE_NEW = MAKE_MENUENTRY( s_NewSaveGame, &MF_Minifont, &MEF_LoadSave, &MEO_SAVE_NEW, String ); -static MenuEntry_t *ME_SAVE; -static MenuEntry_t **MEL_SAVE; - -CVAR_UNAMED(Int, soundrate) -CVAR_UNAMED(Int, soundvoices) -CVAR_UNAMED(Int, musicdevice) -static MenuOption_t MEO_SOUND = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &snd_enabled ); -static MenuEntry_t ME_SOUND = MAKE_MENUENTRY( "Sound:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND, Option ); - -static MenuOption_t MEO_SOUND_MUSIC = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &mus_enabled ); -static MenuEntry_t ME_SOUND_MUSIC = MAKE_MENUENTRY( "Music:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_MUSIC, Option ); - -static char const s_Volume[] = "Volume:"; - -static MenuRangeInt32_t MEO_SOUND_VOLUME_FX = MAKE_MENURANGE( &snd_fxvolume, &MF_Redfont, 0, 255, 0, 33, 2 ); -static MenuEntry_t ME_SOUND_VOLUME_FX = MAKE_MENUENTRY( s_Volume, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SOUND_VOLUME_FX, RangeInt32 ); - -static MenuRangeInt32_t MEO_SOUND_VOLUME_MUSIC = MAKE_MENURANGE( &mus_volume, &MF_Redfont, 0, 255, 0, 33, 2 ); -static MenuEntry_t ME_SOUND_VOLUME_MUSIC = MAKE_MENUENTRY( s_Volume, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SOUND_VOLUME_MUSIC, RangeInt32 ); - -#ifndef EDUKE32_STANDALONE -static MenuOption_t MEO_SOUND_DUKETALK = MAKE_MENUOPTION(&MF_Redfont, &MEOS_NoYes, NULL); -static MenuEntry_t ME_SOUND_DUKETALK = MAKE_MENUENTRY( "Duke talk:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_DUKETALK, Option ); -#else -static MenuOption_t MEO_SOUND_DUKETALK = MAKE_MENUOPTION(&MF_Redfont, &MEOS_YesNo, NULL); -static MenuEntry_t ME_SOUND_DUKETALK = MAKE_MENUENTRY("Silent protagonist:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_DUKETALK, Option); -#endif - -static char const *MEOSN_SOUND_SAMPLINGRATE[] = { "22050Hz", "44100Hz", "48000Hz", }; -static int32_t MEOSV_SOUND_SAMPLINGRATE[] = { 22050, 44100, 48000, }; -static MenuOptionSet_t MEOS_SOUND_SAMPLINGRATE = MAKE_MENUOPTIONSET( MEOSN_SOUND_SAMPLINGRATE, MEOSV_SOUND_SAMPLINGRATE, 0x3 ); -static MenuOption_t MEO_SOUND_SAMPLINGRATE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_SOUND_SAMPLINGRATE, &soundrate ); -static MenuEntry_t ME_SOUND_SAMPLINGRATE = MAKE_MENUENTRY( "Sample rate:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_SAMPLINGRATE, Option ); - -#ifndef EDUKE32_SIMPLE_MENU -static MenuRangeInt32_t MEO_SOUND_NUMVOICES = MAKE_MENURANGE( &soundvoices, &MF_Redfont, 16, 128, 0, 8, 1 ); -static MenuEntry_t ME_SOUND_NUMVOICES = MAKE_MENUENTRY( "Voices:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_NUMVOICES, RangeInt32 ); -#endif - -static char const *MEOSN_SOUND_MIDIDRIVER[] = { - "OPL3", -#ifdef _WIN32 - "Windows", -#endif -}; -static int32_t MEOSV_SOUND_MIDIDRIVER[] = { - ASS_OPL3, -#ifdef _WIN32 - ASS_WinMM, -#endif -}; - -static MenuOptionSet_t MEOS_SOUND_MIDIDRIVER = MAKE_MENUOPTIONSET( MEOSN_SOUND_MIDIDRIVER, MEOSV_SOUND_MIDIDRIVER, 0x2 ); -static MenuOption_t MEO_SOUND_MIDIDRIVER = MAKE_MENUOPTION( &MF_Redfont, &MEOS_SOUND_MIDIDRIVER, &musicdevice ); -static MenuEntry_t ME_SOUND_MIDIDRIVER = MAKE_MENUENTRY( "MIDI driver:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_MIDIDRIVER, Option ); - -static MenuEntry_t ME_SOUND_RESTART = MAKE_MENUENTRY( "Apply Changes", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_NULL, Link ); - -#ifndef EDUKE32_SIMPLE_MENU -static MenuLink_t MEO_ADVSOUND = { MENU_ADVSOUND, MA_Advance, }; -static MenuEntry_t ME_SOUND_ADVSOUND = MAKE_MENUENTRY( "Advanced", &MF_Redfont, &MEF_BigOptionsRt, &MEO_ADVSOUND, Link ); -#endif - -static MenuEntry_t *MEL_SOUND[] = { - &ME_SOUND, - &ME_SOUND_VOLUME_FX, - &ME_SOUND_MUSIC, - &ME_SOUND_VOLUME_MUSIC, - &ME_SOUND_DUKETALK, -#ifndef EDUKE32_SIMPLE_MENU - &ME_SOUND_ADVSOUND, -#endif -}; - -static MenuEntry_t *MEL_ADVSOUND[] = { - &ME_SOUND_SAMPLINGRATE, - &ME_Space2_Redfont, -#ifndef EDUKE32_SIMPLE_MENU - &ME_SOUND_NUMVOICES, - &ME_Space2_Redfont, -#endif - &ME_SOUND_MIDIDRIVER, - &ME_SOUND_RESTART, -}; - - -static MenuOption_t MEO_SAVESETUP_AUTOSAVE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &cl_autosave ); -static MenuEntry_t ME_SAVESETUP_AUTOSAVE = MAKE_MENUENTRY( "Checkpoints:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SAVESETUP_AUTOSAVE, Option ); - -static MenuOption_t MEO_SAVESETUP_AUTOSAVEDELETION = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &cl_autosavedeletion ); -static MenuEntry_t ME_SAVESETUP_AUTOSAVEDELETION = MAKE_MENUENTRY( "Auto-Delete:", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SAVESETUP_AUTOSAVEDELETION, Option ); -static MenuRangeInt32_t MEO_SAVESETUP_MAXAUTOSAVES = MAKE_MENURANGE( &cl_maxautosaves, &MF_Redfont, 1, 10, 0, 10, 1 ); -static MenuEntry_t ME_SAVESETUP_MAXAUTOSAVES = MAKE_MENUENTRY( "Limit:", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SAVESETUP_MAXAUTOSAVES, RangeInt32 ); - -static MenuEntry_t ME_SAVESETUP_CLEANUP = MAKE_MENUENTRY( "Clean Up Saves", &MF_Redfont, &MEF_BigOptionsRt, &MEO_NULL, Link ); - -static MenuEntry_t *MEL_SAVESETUP[] = { - &ME_SAVESETUP_AUTOSAVE, - &ME_SAVESETUP_AUTOSAVEDELETION, - &ME_SAVESETUP_MAXAUTOSAVES, - &ME_SAVESETUP_CLEANUP, -}; - - -MAKE_MENU_TOP_ENTRYLINK( "Player Setup", MEF_CenterMenu, NETWORK_PLAYERSETUP, MENU_PLAYER ); -MAKE_MENU_TOP_ENTRYLINK( "Join Game", MEF_CenterMenu, NETWORK_JOINGAME, MENU_NETJOIN ); -MAKE_MENU_TOP_ENTRYLINK( "Host Game", MEF_CenterMenu, NETWORK_HOSTGAME, MENU_NETHOST ); - -static MenuEntry_t *MEL_NETWORK[] = { - &ME_NETWORK_PLAYERSETUP, - &ME_NETWORK_JOINGAME, - &ME_NETWORK_HOSTGAME, -}; - -//static MenuString_t MEO_PLAYER_NAME = MAKE_MENUSTRING( playername, &MF_Bluefont, MAXPLAYERNAME, 0 ); -//static MenuEntry_t ME_PLAYER_NAME = MAKE_MENUENTRY( "Name", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_NAME, String ); -static char const *MEOSN_PLAYER_COLOR[] = { "Auto", "Blue", "Red", "Green", "Gray", "Dark gray", "Dark green", "Brown", "Dark blue", "Bright red", "Yellow", }; -static int32_t MEOSV_PLAYER_COLOR[] = { 0, 9, 10, 11, 12, 13, 14, 15, 16, 21, 23, }; -static MenuOptionSet_t MEOS_PLAYER_COLOR = MAKE_MENUOPTIONSET( MEOSN_PLAYER_COLOR, MEOSV_PLAYER_COLOR, 0x2 ); -static MenuOption_t MEO_PLAYER_COLOR = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_PLAYER_COLOR, &playercolor ); -static MenuEntry_t ME_PLAYER_COLOR = MAKE_MENUENTRY( "Color", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_COLOR, Option ); -static char const *MEOSN_PLAYER_TEAM[] = { "Blue", "Red", "Green", "Gray", }; -static MenuOptionSet_t MEOS_PLAYER_TEAM = MAKE_MENUOPTIONSET( MEOSN_PLAYER_TEAM, NULL, 0x2 ); -static MenuOption_t MEO_PLAYER_TEAM = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_PLAYER_TEAM, &playerteam ); -static MenuEntry_t ME_PLAYER_TEAM = MAKE_MENUENTRY( "Team", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_TEAM, Option ); -#ifndef EDUKE32_SIMPLE_MENU -static MenuLink_t MEO_PLAYER_MACROS = { MENU_MACROS, MA_Advance, }; -static MenuEntry_t ME_PLAYER_MACROS = MAKE_MENUENTRY( "Multiplayer macros", &MF_Bluefont, &MEF_SmallOptions, &MEO_PLAYER_MACROS, Link ); -#endif - -static MenuEntry_t *MEL_PLAYER[] = { - //&ME_PLAYER_NAME, - &ME_Space4_Bluefont, - &ME_PLAYER_COLOR, - &ME_Space4_Bluefont, - &ME_PLAYER_TEAM, -#ifndef EDUKE32_SIMPLE_MENU - &ME_Space8_Bluefont, - &ME_PLAYER_MACROS, -#endif -}; - -#define MAXRIDECULE 10 -#define MAXRIDECULELENGTH 40 -static MenuString_t MEO_MACROS_TEMPLATE = MAKE_MENUSTRING( NULL, &MF_Bluefont, MAXRIDECULELENGTH, 0 ); -static MenuString_t MEO_MACROS[10]; -static MenuEntry_t ME_MACROS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Macros, &MEO_MACROS_TEMPLATE, String ); -static char sink[50]; -static MenuEntry_t ME_MACROS[MAXRIDECULE]; -static MenuEntry_t *MEL_MACROS[MAXRIDECULE]; - -#ifndef EDUKE32_SIMPLE_MENU -static char const *MenuUserMap = "User Map"; -#endif -static char const *MenuSkillNone = "None"; - -static char const *MEOSN_NetGametypes[MAXGAMETYPES]; -static char const *MEOSN_NetEpisodes[MAXVOLUMES+1]; -static int32_t MEOSV_NetEpisodes[MAXVOLUMES+1]; -static char const *MEOSN_NetLevels[MAXVOLUMES][MAXLEVELS]; -static char const *MEOSN_NetSkills[MAXSKILLS+1]; - -static MenuLink_t MEO_NETHOST_OPTIONS = { MENU_NETOPTIONS, MA_Advance, }; -static MenuEntry_t ME_NETHOST_OPTIONS = MAKE_MENUENTRY( "Game Options", &MF_Redfont, &MEF_VideoSetup, &MEO_NETHOST_OPTIONS, Link ); -static MenuEntry_t ME_NETHOST_LAUNCH = MAKE_MENUENTRY( "Launch Game", &MF_Redfont, &MEF_VideoSetup, &MEO_NULL, Link ); - -static MenuEntry_t *MEL_NETHOST[] = { - &ME_NETHOST_OPTIONS, - &ME_NETHOST_LAUNCH, -}; - -static MenuOptionSet_t MEOS_NETOPTIONS_GAMETYPE = MAKE_MENUOPTIONSET( MEOSN_NetGametypes, NULL, 0x0 ); -static MenuOption_t MEO_NETOPTIONS_GAMETYPE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_GAMETYPE, &m_coop ); -static MenuEntry_t ME_NETOPTIONS_GAMETYPE = MAKE_MENUENTRY( "Game Type", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_GAMETYPE, Option ); -static MenuOptionSet_t MEOS_NETOPTIONS_EPISODE = MAKE_MENUOPTIONSET( MEOSN_NetEpisodes, MEOSV_NetEpisodes, 0x0 ); -CVAR_UNAMED(Int, NetEpisode); -static MenuOption_t MEO_NETOPTIONS_EPISODE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_EPISODE, &NetEpisode ); -static MenuEntry_t ME_NETOPTIONS_EPISODE = MAKE_MENUENTRY( "Episode", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_EPISODE, Option ); -static MenuOptionSet_t MEOS_NETOPTIONS_LEVEL_TEMPLATE = MAKE_MENUOPTIONSETNULL; -static MenuOptionSet_t MEOS_NETOPTIONS_LEVEL[MAXVOLUMES]; -static MenuOption_t MEO_NETOPTIONS_LEVEL = MAKE_MENUOPTION( &MF_Bluefont, NULL, &m_level_number ); -static MenuEntry_t ME_NETOPTIONS_LEVEL = MAKE_MENUENTRY( "Level", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_LEVEL, Option ); -static MenuLink_t MEO_NETOPTIONS_USERMAP = { MENU_NETUSERMAP, MA_Advance, }; -static MenuEntry_t ME_NETOPTIONS_USERMAP = MAKE_MENUENTRY( "User Map", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_USERMAP, Link ); -static MenuOptionSet_t MEOS_NETOPTIONS_MONSTERS = MAKE_MENUOPTIONSET( MEOSN_NetSkills, NULL, 0x0 ); -static MenuOption_t MEO_NETOPTIONS_MONSTERS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_MONSTERS, NULL ); -static MenuEntry_t ME_NETOPTIONS_MONSTERS = MAKE_MENUENTRY( "Monsters", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MONSTERS, Option ); -static MenuOption_t MEO_NETOPTIONS_MARKERS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &m_marker ); -static MenuEntry_t ME_NETOPTIONS_MARKERS = MAKE_MENUENTRY( "Markers", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MARKERS, Option ); -static MenuOption_t MEO_NETOPTIONS_MAPEXITS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OnOff, &m_noexits ); -static MenuEntry_t ME_NETOPTIONS_MAPEXITS = MAKE_MENUENTRY( "Map Exits", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MAPEXITS, Option ); -static MenuOption_t MEO_NETOPTIONS_FRFIRE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &m_ffire ); -static MenuEntry_t ME_NETOPTIONS_FRFIRE = MAKE_MENUENTRY( "Fr. Fire", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_FRFIRE, Option ); -static MenuEntry_t ME_NETOPTIONS_ACCEPT = MAKE_MENUENTRY( "Accept", &MF_Redfont, &MEF_NetSetup_Confirm, &MEO_NETWORK_HOSTGAME, Link ); - -static MenuEntry_t *MEL_NETOPTIONS[] = { - &ME_NETOPTIONS_GAMETYPE, - &ME_NETOPTIONS_EPISODE, - &ME_NETOPTIONS_LEVEL, - &ME_NETOPTIONS_MONSTERS, - &ME_NETOPTIONS_MARKERS, - &ME_NETOPTIONS_MAPEXITS, - &ME_NETOPTIONS_ACCEPT, -}; - -static char MenuServer[BMAX_PATH] = "localhost"; -static MenuString_t MEO_NETJOIN_SERVER = MAKE_MENUSTRING( MenuServer, &MF_Bluefont, BMAX_PATH, 0 ); -static MenuEntry_t ME_NETJOIN_SERVER = MAKE_MENUENTRY( "Server", &MF_Redfont, &MEF_VideoSetup, &MEO_NETJOIN_SERVER, String ); -#define MAXPORTSTRINGLENGTH 6 // unsigned 16-bit integer -static char MenuPort[MAXPORTSTRINGLENGTH] = "19014"; -static MenuString_t MEO_NETJOIN_PORT = MAKE_MENUSTRING( MenuPort, &MF_Bluefont, MAXPORTSTRINGLENGTH, INPUT_NUMERIC ); -static MenuEntry_t ME_NETJOIN_PORT = MAKE_MENUENTRY( "Port", &MF_Redfont, &MEF_VideoSetup, &MEO_NETJOIN_PORT, String ); -static MenuEntry_t ME_NETJOIN_CONNECT = MAKE_MENUENTRY( "Connect", &MF_Redfont, &MEF_VideoSetup_Apply, &MEO_NULL, Link ); - -static MenuEntry_t *MEL_NETJOIN[] = { - &ME_NETJOIN_SERVER, - &ME_NETJOIN_PORT, - &ME_NETJOIN_CONNECT, -}; - - -#define NoTitle NULL - -#define MAKE_MENUMENU(Title, Format, Entries) { Title, Format, Entries, ARRAY_SIZE(Entries), 0, 0, 0 } -#define MAKE_MENUMENU_CUSTOMSIZE(Title, Format, Entries) { Title, Format, Entries, 0, 0, 0, 0 } - -static MenuMenu_t M_MAIN = MAKE_MENUMENU( NoTitle, &MMF_Top_Main, MEL_MAIN ); -static MenuMenu_t M_MAIN_INGAME = MAKE_MENUMENU( NoTitle, &MMF_Top_Main, MEL_MAIN_INGAME ); -static MenuMenu_t M_EPISODE = MAKE_MENUMENU( "Select An Episode", &MMF_Top_Episode, MEL_EPISODE ); -static MenuMenu_t M_SKILL = MAKE_MENUMENU( "Select Skill", &MMF_Top_Skill, MEL_SKILL ); -static MenuMenu_t M_NEWGAMECUSTOM = MAKE_MENUMENU( s_NewGame, &MMF_Top_NewGameCustom, MEL_NEWGAMECUSTOM ); -static MenuMenu_t M_NEWGAMECUSTOMSUB = MAKE_MENUMENU( s_NewGame, &MMF_Top_NewGameCustomSub, MEL_NEWGAMECUSTOMSUB ); -#ifndef EDUKE32_SIMPLE_MENU -static MenuMenu_t M_GAMESETUP = MAKE_MENUMENU( "Game Setup", &MMF_BigOptions, MEL_GAMESETUP ); -#endif -static MenuMenu_t M_OPTIONS = MAKE_MENUMENU( s_Options, &MMF_Top_Options, MEL_OPTIONS ); -static MenuMenu_t M_VIDEOSETUP = MAKE_MENUMENU( "Video Mode", &MMF_BigOptions, MEL_VIDEOSETUP ); -static MenuMenu_t M_KEYBOARDSETUP = MAKE_MENUMENU( "Configure Controls", &MMF_Top_Options, MEL_KEYBOARDSETUP ); -static MenuMenu_t M_CONTROLS = MAKE_MENUMENU( "Control Setup", &MMF_BigOptions, MEL_CONTROLS ); -static MenuMenu_t M_CHEATS = MAKE_MENUMENU( "Cheats", &MMF_SmallOptions, MEL_CHEATS ); -static MenuMenu_t M_MOUSESETUP = MAKE_MENUMENU( "Mouse Setup", &MMF_BigOptions, MEL_MOUSESETUP ); -#ifdef EDUKE32_ANDROID_MENU -static MenuMenu_t M_TOUCHSETUP = MAKE_MENUMENU( "Touch Setup", &MMF_Top_Options, MEL_TOUCHSETUP ); -static MenuMenu_t M_TOUCHSENS = MAKE_MENUMENU( "Sensitivity", &MMF_BigOptions, MEL_TOUCHSENS); -static MenuPanel_t M_TOUCHBUTTONS = { "Button Setup", MENU_TOUCHSETUP, MA_Return, MENU_TOUCHSETUP, MA_Advance, }; -#endif -static MenuMenu_t M_JOYSTICKSETUP = MAKE_MENUMENU( "Gamepad Setup", &MMF_BigOptions, MEL_JOYSTICKSETUP ); -static MenuMenu_t M_JOYSTICKAXES = MAKE_MENUMENU( "Gamepad Axes", &MMF_BigSliders, MEL_JOYSTICKAXES ); -static MenuMenu_t M_KEYBOARDKEYS = MAKE_MENUMENU( "Key Configuration", &MMF_KeyboardSetupFuncs, MEL_KEYBOARDSETUPFUNCS ); -static MenuMenu_t M_MOUSEADVANCED = MAKE_MENUMENU( "Advanced Mouse", &MMF_BigSliders, MEL_MOUSEADVANCED ); -static MenuMenu_t M_JOYSTICKAXIS = MAKE_MENUMENU( NULL, &MMF_BigSliders, MEL_JOYSTICKAXIS ); -#ifdef USE_OPENGL -static MenuMenu_t M_RENDERERSETUP_POLYMOST = MAKE_MENUMENU( "Polymost Setup", &MMF_SmallOptions, MEL_RENDERERSETUP_POLYMOST ); -# ifdef POLYMER -static MenuMenu_t M_RENDERERSETUP_POLYMER = MAKE_MENUMENU("Polymer Setup", &MMF_SmallOptions, MEL_RENDERERSETUP_POLYMER ); -# endif -#endif -static MenuMenu_t M_COLCORR = MAKE_MENUMENU( "Color Correction", &MMF_ColorCorrect, MEL_COLCORR ); -static MenuMenu_t M_SCREENSETUP = MAKE_MENUMENU( "HUD Setup", &MMF_BigOptions, MEL_SCREENSETUP ); -static MenuMenu_t M_DISPLAYSETUP = MAKE_MENUMENU( "Display Setup", &MMF_BigOptions, MEL_DISPLAYSETUP ); -static MenuMenu_t M_LOAD = MAKE_MENUMENU_CUSTOMSIZE( s_LoadGame, &MMF_LoadSave, MEL_LOAD ); -static MenuMenu_t M_SAVE = MAKE_MENUMENU_CUSTOMSIZE( s_SaveGame, &MMF_LoadSave, MEL_SAVE ); -static MenuMenu_t M_SOUND = MAKE_MENUMENU( "Sound Setup", &MMF_BigOptions, MEL_SOUND ); -static MenuMenu_t M_ADVSOUND = MAKE_MENUMENU( "Advanced Sound", &MMF_BigOptions, MEL_ADVSOUND ); -static MenuMenu_t M_SAVESETUP = MAKE_MENUMENU( "Save Setup", &MMF_BigOptions, MEL_SAVESETUP ); -static MenuMenu_t M_NETWORK = MAKE_MENUMENU( "Network Game", &MMF_Top_Joystick_Network, MEL_NETWORK ); -static MenuMenu_t M_PLAYER = MAKE_MENUMENU( "Player Setup", &MMF_SmallOptions, MEL_PLAYER ); -static MenuMenu_t M_MACROS = MAKE_MENUMENU( "Multiplayer Macros", &MMF_Macros, MEL_MACROS ); -static MenuMenu_t M_NETHOST = MAKE_MENUMENU( "Host Network Game", &MMF_SmallOptionsNarrow, MEL_NETHOST ); -static MenuMenu_t M_NETOPTIONS = MAKE_MENUMENU( "Net Game Options", &MMF_NetSetup, MEL_NETOPTIONS ); -static MenuMenu_t M_NETJOIN = MAKE_MENUMENU( "Join Network Game", &MMF_SmallOptionsNarrow, MEL_NETJOIN ); - -#ifdef EDUKE32_SIMPLE_MENU -static MenuPanel_t M_STORY = { NoTitle, MENU_STORY, MA_Return, MENU_STORY, MA_Advance, }; -#else -static MenuPanel_t M_STORY = { NoTitle, MENU_F1HELP, MA_Return, MENU_F1HELP, MA_Advance, }; -#endif - -static MenuPanel_t M_F1HELP = { NoTitle, MENU_STORY, MA_Return, MENU_STORY, MA_Advance, }; -static MenuPanel_t M_CREDITS = { NoTitle, MENU_CREDITS5, MA_Return, MENU_CREDITS2, MA_Advance, }; -static MenuPanel_t M_CREDITS2 = { NoTitle, MENU_CREDITS, MA_Return, MENU_CREDITS3, MA_Advance, }; -static MenuPanel_t M_CREDITS3 = { NoTitle, MENU_CREDITS2, MA_Return, MENU_CREDITS4, MA_Advance, }; -static MenuPanel_t M_CREDITS4 = { "About " APPNAME, MENU_CREDITS3, MA_Return, MENU_CREDITS5, MA_Advance, }; -static MenuPanel_t M_CREDITS5 = { "About " APPNAME, MENU_CREDITS4, MA_Return, MENU_CREDITS, MA_Advance, }; - -#define CURSOR_CENTER_2LINE { MENU_MARGIN_CENTER<<16, 120<<16, } -#define CURSOR_CENTER_3LINE { MENU_MARGIN_CENTER<<16, 129<<16, } -#define CURSOR_BOTTOMRIGHT { 304<<16, 186<<16, } - -static MenuVerify_t M_SAVECLEANVERIFY = { CURSOR_CENTER_3LINE, MENU_SAVESETUP, MA_None, }; -static MenuVerify_t M_QUIT = { CURSOR_CENTER_2LINE, MENU_CLOSE, MA_None, }; -static MenuVerify_t M_QUITTOTITLE = { CURSOR_CENTER_2LINE, MENU_CLOSE, MA_None, }; -static MenuVerify_t M_LOADVERIFY = { CURSOR_CENTER_3LINE, MENU_CLOSE, MA_None, }; -static MenuVerify_t M_LOADDELVERIFY = { CURSOR_CENTER_3LINE, MENU_LOAD, MA_None, }; -static MenuVerify_t M_NEWVERIFY = { CURSOR_CENTER_2LINE, MENU_EPISODE, MA_Advance, }; -static MenuVerify_t M_SAVEVERIFY = { CURSOR_CENTER_2LINE, MENU_SAVE, MA_None, }; -static MenuVerify_t M_SAVEDELVERIFY = { CURSOR_CENTER_3LINE, MENU_SAVE, MA_None, }; -static MenuVerify_t M_RESETPLAYER = { CURSOR_CENTER_3LINE, MENU_CLOSE, MA_None, }; - -static MenuVerify_t M_COLCORRRESETVERIFY = { CURSOR_CENTER_2LINE, MENU_COLCORR, MA_None, }; -static MenuVerify_t M_KEYSRESETVERIFY = { CURSOR_CENTER_2LINE, MENU_KEYBOARDSETUP, MA_None, }; -static MenuVerify_t M_KEYSCLASSICVERIFY = { CURSOR_CENTER_2LINE, MENU_KEYBOARDSETUP, MA_None, }; -static MenuVerify_t M_JOYSTANDARDVERIFY = { CURSOR_CENTER_2LINE, MENU_JOYSTICKSETUP, MA_None, }; -static MenuVerify_t M_JOYPROVERIFY = { CURSOR_CENTER_2LINE, MENU_JOYSTICKSETUP, MA_None, }; -static MenuVerify_t M_JOYCLEARVERIFY = { CURSOR_CENTER_2LINE, MENU_JOYSTICKSETUP, MA_None, }; - -static MenuMessage_t M_NETWAITMASTER = { CURSOR_BOTTOMRIGHT, MENU_NULL, MA_None, }; -static MenuMessage_t M_NETWAITVOTES = { CURSOR_BOTTOMRIGHT, MENU_NULL, MA_None, }; -static MenuMessage_t M_BUYDUKE = { CURSOR_BOTTOMRIGHT, MENU_EPISODE, MA_Return, }; - -static MenuTextForm_t M_ADULTPASSWORD = { NULL, "Enter Password:", MAXPWLOCKOUT, MTF_Password }; -static MenuTextForm_t M_CHEATENTRY = { NULL, "Enter Cheat Code:", MAXCHEATLEN, 0 }; -static MenuTextForm_t M_CHEAT_WARP = { NULL, "Enter Warp #:", 3, 0 }; -static MenuTextForm_t M_CHEAT_SKILL = { NULL, "Enter Skill #:", 1, 0 }; - -//#define MAKE_MENUFILESELECT(a, dir, b, c) { a, { &MMF_FileSelectLeft, &MMF_FileSelectRight }, { &MF_Minifont, &MF_Minifont }, dir, b, c, { NULL, NULL }, { 0, 0 }, { 3<<16, 3<<16 }, FNLIST_INITIALIZER, 0 } - -//static MenuFileSelect_t M_USERMAP = MAKE_MENUFILESELECT( "Select A User Map", "./usermaps/", "*.map", boardfilename ); - -// MUST be in ascending order of MenuID enum values due to binary search -static Menu_t Menus[] = { - { &M_MAIN, MENU_MAIN, MENU_CLOSE, MA_None, Menu }, - { &M_MAIN_INGAME, MENU_MAIN_INGAME, MENU_CLOSE, MA_None, Menu }, - { &M_EPISODE, MENU_EPISODE, MENU_MAIN, MA_Return, Menu }, - //{ &M_USERMAP, MENU_USERMAP, MENU_PREVIOUS, MA_Return, FileSelect }, - { &M_NEWGAMECUSTOM, MENU_NEWGAMECUSTOM, MENU_MAIN, MA_Return, Menu }, - { &M_NEWGAMECUSTOMSUB, MENU_NEWGAMECUSTOMSUB, MENU_NEWGAMECUSTOM, MA_Return, Menu }, - { &M_SKILL, MENU_SKILL, MENU_PREVIOUS, MA_Return, Menu }, -#ifndef EDUKE32_SIMPLE_MENU - { &M_GAMESETUP, MENU_GAMESETUP, MENU_OPTIONS, MA_Return, Menu }, -#endif - { &M_OPTIONS, MENU_OPTIONS, MENU_MAIN, MA_Return, Menu }, - { &M_VIDEOSETUP, MENU_VIDEOSETUP, MENU_DISPLAYSETUP, MA_Return, Menu }, - { &M_KEYBOARDSETUP, MENU_KEYBOARDSETUP, MENU_CONTROLS, MA_Return, Menu }, - { &M_MOUSESETUP, MENU_MOUSESETUP, MENU_CONTROLS, MA_Return, Menu }, - { &M_JOYSTICKSETUP, MENU_JOYSTICKSETUP, MENU_CONTROLS, MA_Return, Menu }, - { &M_JOYSTICKAXES, MENU_JOYSTICKAXES, MENU_JOYSTICKSETUP, MA_Return, Menu }, - { &M_KEYBOARDKEYS, MENU_KEYBOARDKEYS, MENU_KEYBOARDSETUP, MA_Return, Menu }, - { &M_MOUSEADVANCED, MENU_MOUSEADVANCED, MENU_MOUSESETUP, MA_Return, Menu }, - { &M_JOYSTICKAXIS, MENU_JOYSTICKAXIS, MENU_JOYSTICKAXES, MA_Return, Menu }, - { &M_CONTROLS, MENU_CONTROLS, MENU_OPTIONS, MA_Return, Menu }, -#ifdef USE_OPENGL - { &M_RENDERERSETUP_POLYMOST, MENU_POLYMOST, MENU_DISPLAYSETUP, MA_Return, Menu }, -#endif - { &M_COLCORR, MENU_COLCORR, MENU_DISPLAYSETUP, MA_Return, Menu }, - { &M_COLCORR, MENU_COLCORR_INGAME, MENU_CLOSE, MA_Return, Menu }, - { &M_SCREENSETUP, MENU_SCREENSETUP, MENU_DISPLAYSETUP, MA_Return, Menu }, - { &M_DISPLAYSETUP, MENU_DISPLAYSETUP, MENU_OPTIONS, MA_Return, Menu }, -#ifdef POLYMER - { &M_RENDERERSETUP_POLYMER, MENU_POLYMER, MENU_DISPLAYSETUP, MA_Return, Menu }, -#endif - { &M_LOAD, MENU_LOAD, MENU_MAIN, MA_Return, Menu }, - { &M_SAVE, MENU_SAVE, MENU_MAIN, MA_Return, Menu }, - { &M_STORY, MENU_STORY, MENU_MAIN, MA_Return, Panel }, - { &M_F1HELP, MENU_F1HELP, MENU_MAIN, MA_Return, Panel }, - { &M_QUIT, MENU_QUIT, MENU_PREVIOUS, MA_Return, Verify }, - { &M_QUITTOTITLE, MENU_QUITTOTITLE, MENU_PREVIOUS, MA_Return, Verify }, - { &M_QUIT, MENU_QUIT_INGAME, MENU_CLOSE, MA_None, Verify }, - { &M_NETHOST, MENU_NETSETUP, MENU_MAIN, MA_Return, Menu }, - { &M_NETWAITMASTER, MENU_NETWAITMASTER, MENU_MAIN, MA_Return, Message }, - { &M_NETWAITVOTES, MENU_NETWAITVOTES, MENU_MAIN, MA_Return, Message }, - { &M_SOUND, MENU_SOUND, MENU_OPTIONS, MA_Return, Menu }, - { &M_SOUND, MENU_SOUND_INGAME, MENU_CLOSE, MA_Return, Menu }, - { &M_ADVSOUND, MENU_ADVSOUND, MENU_SOUND, MA_Return, Menu }, - { &M_SAVESETUP, MENU_SAVESETUP, MENU_OPTIONS, MA_Return, Menu }, - { &M_SAVECLEANVERIFY, MENU_SAVECLEANVERIFY, MENU_SAVESETUP, MA_None, Verify }, -#ifdef EDUKE32_SIMPLE_MENU - { &M_CHEATS, MENU_CHEATS, MENU_OPTIONS, MA_Return, Menu }, -#else - { &M_CHEATS, MENU_CHEATS, MENU_GAMESETUP, MA_Return, Menu }, -#endif - { &M_CHEATENTRY, MENU_CHEATENTRY, MENU_CHEATS, MA_None, TextForm }, - { &M_CHEAT_WARP, MENU_CHEAT_WARP, MENU_CHEATS, MA_None, TextForm }, - { &M_CHEAT_SKILL, MENU_CHEAT_SKILL, MENU_CHEATS, MA_None, TextForm }, - { &M_CREDITS, MENU_CREDITS, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS2, MENU_CREDITS2, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS3, MENU_CREDITS3, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS4, MENU_CREDITS4, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS5, MENU_CREDITS5, MENU_MAIN, MA_Return, Panel }, - { &M_LOADVERIFY, MENU_LOADVERIFY, MENU_LOAD, MA_None, Verify }, - { &M_LOADDELVERIFY, MENU_LOADDELVERIFY, MENU_LOAD, MA_None, Verify }, - { &M_NEWVERIFY, MENU_NEWVERIFY, MENU_PREVIOUS, MA_Return, Verify }, - { &M_SAVEVERIFY, MENU_SAVEVERIFY, MENU_SAVE, MA_None, Verify }, - { &M_SAVEDELVERIFY, MENU_SAVEDELVERIFY, MENU_SAVE, MA_None, Verify }, - { &M_COLCORRRESETVERIFY, MENU_COLCORRRESETVERIFY, MENU_COLCORR, MA_None, Verify }, - { &M_KEYSRESETVERIFY, MENU_KEYSRESETVERIFY, MENU_KEYBOARDSETUP, MA_None, Verify }, - { &M_KEYSCLASSICVERIFY, MENU_KEYSCLASSICVERIFY, MENU_KEYBOARDSETUP, MA_None, Verify }, - { &M_JOYSTANDARDVERIFY, MENU_JOYSTANDARDVERIFY, MENU_JOYSTICKSETUP, MA_None, Verify }, - { &M_JOYPROVERIFY, MENU_JOYPROVERIFY, MENU_JOYSTICKSETUP, MA_None, Verify }, - { &M_JOYCLEARVERIFY, MENU_JOYCLEARVERIFY, MENU_JOYSTICKSETUP, MA_None, Verify }, - { &M_ADULTPASSWORD, MENU_ADULTPASSWORD, MENU_GAMESETUP, MA_None, TextForm }, - { &M_RESETPLAYER, MENU_RESETPLAYER, MENU_CLOSE, MA_None, Verify }, - { &M_BUYDUKE, MENU_BUYDUKE, MENU_EPISODE, MA_Return, Message }, - { &M_NETWORK, MENU_NETWORK, MENU_MAIN, MA_Return, Menu }, - { &M_PLAYER, MENU_PLAYER, MENU_OPTIONS, MA_Return, Menu }, - { &M_MACROS, MENU_MACROS, MENU_PLAYER, MA_Return, Menu }, - { &M_NETHOST, MENU_NETHOST, MENU_NETWORK, MA_Return, Menu }, - { &M_NETOPTIONS, MENU_NETOPTIONS, MENU_NETWORK, MA_Return, Menu }, -// { &M_USERMAP, MENU_NETUSERMAP, MENU_NETOPTIONS, MA_Return, FileSelect }, - { &M_NETJOIN, MENU_NETJOIN, MENU_NETWORK, MA_Return, Menu }, -}; - -static CONSTEXPR const uint16_t numMenus = ARRAY_SIZE(Menus); - -Menu_t *m_currentMenu = &Menus[0]; -static Menu_t *m_previousMenu = &Menus[0]; -static Menu_t * m_parentMenu; - -MenuID_t g_currentMenu; -static MenuID_t g_previousMenu; - -#define MenuMenu_ChangeEntryList(m, el)\ - do {\ - m.entrylist = el;\ - m.numEntries = ARRAY_SIZE(el);\ - } while (0) - -static void MenuEntry_DisableOnCondition(MenuEntry_t * const entry, const int32_t condition) -{ - if (condition) - entry->flags |= MEF_Disabled; - else - entry->flags &= ~MEF_Disabled; -} -static void MenuEntry_LookDisabledOnCondition(MenuEntry_t * const entry, const int32_t condition) -{ - if (condition) - entry->flags |= MEF_LookDisabled; - else - entry->flags &= ~MEF_LookDisabled; -} -static void MenuEntry_HideOnCondition(MenuEntry_t * const entry, const int32_t condition) -{ - if (condition) - entry->flags |= MEF_Hidden; - else - entry->flags &= ~MEF_Hidden; -} - -static int32_t M_RunMenu_Menu(Menu_t *cm, MenuMenu_t *menu, MenuEntry_t *currentry, int32_t state, vec2_t origin, bool actually_draw = true); -static void Menu_EntryFocus(/*MenuEntry_t *entry*/); - -static MenuEntry_t *Menu_AdjustForCurrentEntryAssignment(MenuMenu_t *menu) -{ - MenuEntry_t *currentry = menu->entrylist[menu->currentEntry]; - - Menu_EntryFocus(/*currentry*/); - - if (currentry->ybottom - menu->scrollPos > klabs(menu->format->bottomcutoff)) - menu->scrollPos = currentry->ybottom - klabs(menu->format->bottomcutoff); - else if (currentry->ytop - menu->scrollPos < menu->format->pos.y) - menu->scrollPos = currentry->ytop - menu->format->pos.y; - - return currentry; -} - -static MenuEntry_t *Menu_AdjustForCurrentEntryAssignmentBlind(MenuMenu_t *menu) -{ - M_RunMenu_Menu(nullptr, menu, nullptr, 0, { 0, 0 }, false); - return Menu_AdjustForCurrentEntryAssignment(menu); -} - -static int32_t SELECTDIR_z = 65536; - -void Menu_PopulateNewGameCustom(void) -{ - M_NEWGAMECUSTOM.title = s_NewGame; - - int e = 0; - for (MenuGameplayStemEntry const & stem : g_MenuGameplayEntries) - { - MenuGameplayEntry const & entry = stem.entry; - if (!entry.isValid()) - break; - - MEL_NEWGAMECUSTOM[e] = &ME_NEWGAMECUSTOMENTRIES[e]; - - ++e; - } - M_NEWGAMECUSTOM.numEntries = e; - MMF_Top_NewGameCustom.pos.y = (58 + (3-e)*6)<<16; -} - -void Menu_PopulateNewGameCustomSub(int e) -{ - if ((unsigned)e >= MAXMENUGAMEPLAYENTRIES) - return; - - MenuGameplayStemEntry const & stem = g_MenuGameplayEntries[e]; - MenuGameplayEntry const & entry = stem.entry; - if (!entry.isValid()) - return; - - M_NEWGAMECUSTOMSUB.title = entry.name; - - int s = 0; - for (MenuGameplayEntry const & subentry : stem.subentries) - { - if (!subentry.isValid()) - break; - - MEL_NEWGAMECUSTOMSUB[s] = &ME_NEWGAMECUSTOMSUBENTRIES[e][s]; - - ++s; - } - M_NEWGAMECUSTOMSUB.numEntries = s; - MMF_Top_NewGameCustomSub.pos.y = (58 + (3-s)*6)<<16; -} - -/* -This function prepares data after ART and CON have been processed. -It also initializes some data in loops rather than statically at compile time. -*/ void Menu_Init(void) { int32_t i, j, k; if (FURY) - { - MMF_Top_Skill.pos.x = (320<<15); - ME_SKILL_TEMPLATE.format = &MEF_LeftMenu; - } - - // prepare menu fonts - // check if tilenum is -1 in case it was set in EVENT_SETDEFAULTS - if ((unsigned)MF_Redfont.tilenum >= MAXTILES) MF_Redfont.tilenum = BIGALPHANUM; - if ((unsigned)MF_Bluefont.tilenum >= MAXTILES) MF_Bluefont.tilenum = STARTALPHANUM; - if ((unsigned)MF_Minifont.tilenum >= MAXTILES) MF_Minifont.tilenum = MINIFONT; - MF_Redfont.emptychar.y = tilesiz[MF_Redfont.tilenum].y<<16; - MF_Bluefont.emptychar.y = tilesiz[MF_Bluefont.tilenum].y<<16; - MF_Minifont.emptychar.y = tilesiz[MF_Minifont.tilenum].y<<16; - if (!minitext_lowercase) - MF_Minifont.textflags |= TEXT_UPPERCASE; - - // prepare gamefuncs and keys - MEOSN_Gamefuncs[0] = MenuGameFuncNone; - MEOSV_Gamefuncs[0] = -1; - k = 1; - for (i = 0; i < NUMGAMEFUNCTIONS; ++i) - { - MenuGameFuncs[i] = buttonMap.GetButtonAlias(i); - MenuGameFuncs[i].Substitute('_', ' '); - - if (MenuGameFuncs[i][0] != '\0') - { - MEOSN_Gamefuncs[k] = MenuGameFuncs[i]; - MEOSV_Gamefuncs[k] = i; - ++k; - } - } - MEOS_Gamefuncs.numOptions = k; - - for (i = 1; i < NUMKEYS-1; ++i) - MEOSN_Keys[i] = KB_ScanCodeToString(i); - MEOSN_Keys[0] = MenuKeyNone; - MEOSN_Keys[NUMKEYS-1] = MenuKeyNone; - - - // prepare episodes - k = 0; - for (i = 0; i < g_volumeCnt; ++i) - { - if (g_volumeNames[i][0]) - { - if (!(g_volumeFlags[i] & EF_HIDEFROMSP)) - { - MEL_EPISODE[i] = &ME_EPISODE[i]; - ME_EPISODE[i] = ME_EPISODE_TEMPLATE; - ME_EPISODE[i].name = g_volumeNames[i]; - } - - // if (!(EpisodeFlags[i] & EF_HIDEFROMMP)) - { - MEOSN_NetEpisodes[k] = g_volumeNames[i]; - MEOSV_NetEpisodes[k] = i; - - k++; - } - } - - // prepare levels - MEOS_NETOPTIONS_LEVEL[i] = MEOS_NETOPTIONS_LEVEL_TEMPLATE; - for (j = 0; j < MAXLEVELS; ++j) - { - MEOSN_NetLevels[i][j] = g_mapInfo[MAXLEVELS*i+j].name; - if (g_mapInfo[i*MAXLEVELS+j].filename != NULL) - MEOS_NETOPTIONS_LEVEL[i].numOptions = j+1; - } - MEOS_NETOPTIONS_LEVEL[i].optionNames = MEOSN_NetLevels[i]; - } - M_EPISODE.numEntries = g_volumeCnt+2; -#ifndef EDUKE32_SIMPLE_MENU - MEL_EPISODE[g_volumeCnt] = &ME_Space4_Redfont; - MEL_EPISODE[g_volumeCnt+1] = &ME_EPISODE_USERMAP; - MEOSN_NetEpisodes[k] = MenuUserMap; - MEOSV_NetEpisodes[k] = MAXVOLUMES; -#else - M_EPISODE.numEntries = g_volumeCnt; - k--; -#endif - MEOS_NETOPTIONS_EPISODE.numOptions = k + 1; - NetEpisode = MEOSV_NetEpisodes[0]; - MMF_Top_Episode.pos.y = (58 + (3-k)*6)<<16; - if (g_skillCnt == 0) - MEO_EPISODE.linkID = MENU_NULL; - M_EPISODE.currentEntry = ud.default_volume; - - // prepare new game custom :O - if (g_MenuGameplayEntries[0].entry.isValid()) - { - MEO_MAIN_NEWGAME.linkID = M_NEWVERIFY.linkID = MENU_NEWGAMECUSTOM; - - int e = 0; - for (MenuGameplayStemEntry const & stem : g_MenuGameplayEntries) - { - MenuGameplayEntry const & entry = stem.entry; - if (!entry.isValid()) - break; - - MenuEntry_t & e_me = ME_NEWGAMECUSTOMENTRIES[e]; - e_me = ME_EPISODE_TEMPLATE; - MenuLink_t & e_meo = MEO_NEWGAMECUSTOM[e]; - e_meo = MEO_NEWGAMECUSTOM_TEMPLATE; - e_me.entry = &e_meo; - - e_me.name = entry.name; - if (entry.flags & MGE_Locked) - e_me.flags |= MEF_Disabled; - if (entry.flags & MGE_Hidden) - e_me.flags |= MEF_Hidden; - - int s = 0; - for (MenuGameplayEntry const & subentry : stem.subentries) - { - if (!subentry.isValid()) - break; - - MenuEntry_t & s_me = ME_NEWGAMECUSTOMSUBENTRIES[e][s]; - s_me = ME_EPISODE_TEMPLATE; - MenuLink_t & s_meo = MEO_NEWGAMECUSTOMSUB[e][s]; - s_meo = MEO_NEWGAMECUSTOMSUB_TEMPLATE; - s_me.entry = &s_meo; - - s_me.name = subentry.name; - if (subentry.flags & MGE_Locked) - s_me.flags |= MEF_Disabled; - if (subentry.flags & MGE_Hidden) - s_me.flags |= MEF_Hidden; - - ++s; - } - - if (entry.flags & MGE_UserContent) - e_meo.linkID = MENU_USERMAP; - else if (s == 0) - e_meo.linkID = MENU_SKILL; - - ++e; - } - - Menu_PopulateNewGameCustom(); - } - - // prepare skills - k = -1; - for (i = 0; i < g_skillCnt && g_skillNames[i][0]; ++i) - { - MEL_SKILL[i] = &ME_SKILL[i]; - ME_SKILL[i] = ME_SKILL_TEMPLATE; - ME_SKILL[i].name = g_skillNames[i]; - - MEOSN_NetSkills[i] = g_skillNames[i]; - - k = i; - } - ++k; - M_SKILL.numEntries = g_skillCnt; // k; - MEOS_NETOPTIONS_MONSTERS.numOptions = g_skillCnt + 1; // k+1; - MEOSN_NetSkills[g_skillCnt] = MenuSkillNone; - MMF_Top_Skill.pos.y = (58 + (4-g_skillCnt)*6)<<16; - M_SKILL.currentEntry = ud.default_skill; - Menu_AdjustForCurrentEntryAssignmentBlind(&M_SKILL); - - // prepare multiplayer gametypes - k = -1; - for (i = 0; i < MAXGAMETYPES; ++i) - if (g_gametypeNames[i][0]) - { - MEOSN_NetGametypes[i] = g_gametypeNames[i]; - k = i; - } - ++k; - MEOS_NETOPTIONS_GAMETYPE.numOptions = k; - if (NAM_WW2GI) - ME_NETOPTIONS_MONSTERS.name = "Enemies"; - - // prepare cheats - for (i = 0; i < NUMCHEATFUNCS; ++i) - MEL_CHEATS[i+1] = &ME_CheatCodes[i]; - - // prepare text chat macros - for (i = 0; i < MAXRIDECULE; ++i) - { - MEL_MACROS[i] = &ME_MACROS[i]; - ME_MACROS[i] = ME_MACROS_TEMPLATE; - ME_MACROS[i].entry = &MEO_MACROS[i]; - MEO_MACROS[i] = MEO_MACROS_TEMPLATE; - - MEO_MACROS[i].variable = sink;// ud.ridecule[i]; temporarily disabled - } - - // prepare input - for (i = 0; i < NUMGAMEFUNCTIONS; ++i) - { - if (MenuGameFuncs[i][0] == '\0') - { - MEL_KEYBOARDSETUPFUNCS[i] = NULL; - continue; - } - - MEL_KEYBOARDSETUPFUNCS[i] = &ME_KEYBOARDSETUPFUNCS[i]; - ME_KEYBOARDSETUPFUNCS[i] = ME_KEYBOARDSETUPFUNCS_TEMPLATE; - ME_KEYBOARDSETUPFUNCS[i].name = MenuGameFuncs[i]; - ME_KEYBOARDSETUPFUNCS[i].entry = &MEO_KEYBOARDSETUPFUNCS[i]; - MEO_KEYBOARDSETUPFUNCS[i] = MEO_KEYBOARDSETUPFUNCS_TEMPLATE; - } - M_KEYBOARDKEYS.numEntries = NUMGAMEFUNCTIONS; - for (i = 0; i < 2*joystick.numButtons + 8*joystick.numHats; ++i) - { - if (i < 2*joystick.numButtons) - { - if (i & 1) - Bsnprintf(MenuJoystickNames[i], MAXJOYBUTTONSTRINGLENGTH, "Double %s", joyGetName(1, i>>1)); - else - Bstrncpy(MenuJoystickNames[i], joyGetName(1, i>>1), MAXJOYBUTTONSTRINGLENGTH); - } - else - { - Bsnprintf(MenuJoystickNames[i], MAXJOYBUTTONSTRINGLENGTH, (i & 1) ? "Double Hat %d %s" : "Hat %d %s", ((i - 2*joystick.numButtons)>>3), MenuJoystickHatDirections[((i - 2*joystick.numButtons)>>1) % 4]); - } - } - for (i = 0; i < joystick.numAxes; ++i) - { - ME_JOYSTICKAXES[i] = ME_JOYSTICKAXES_TEMPLATE; - Bstrncpy(MenuJoystickAxes[i], joyGetName(0, i), MAXJOYBUTTONSTRINGLENGTH); - ME_JOYSTICKAXES[i].name = MenuJoystickAxes[i]; - MEL_JOYSTICKAXES[i] = &ME_JOYSTICKAXES[i]; - } - M_JOYSTICKAXES.numEntries = joystick.numAxes; - - // prepare sound setup -#ifndef EDUKE32_STANDALONE - if (WW2GI) - ME_SOUND_DUKETALK.name = "GI talk:"; - else if (NAM) - ME_SOUND_DUKETALK.name = "Grunt talk:"; -#endif - - if (FURY) - { - MF_Redfont.between.x = 2<<16; - MF_Redfont.cursorScale = 32768; - MF_Redfont.zoom = 16384; - MF_Bluefont.zoom = 16384; - - // hack; should swap out pointers - MF_Minifont = MF_Bluefont; - - MMF_Top_Main.pos.x = 40<<16; - MMF_Top_Main.pos.y = 130<<16; - MMF_Top_Main.bottomcutoff = 190<<16; - M_OPTIONS.format = &MMF_Top_Main; - - MEF_MainMenu.width = MEF_OptionsMenu.width = -(160<<16); - MEF_MainMenu.marginBottom = 7<<16; - - M_OPTIONS.title = NoTitle; - - SELECTDIR_z = 16384; - } - // prepare shareware if (VOLUMEONE) { @@ -1811,321 +69,10 @@ void Menu_Init(void) MenuEntry_DisableOnCondition(&ME_NETOPTIONS_EPISODE, 1); } - // prepare pre-Atomic - if (!VOLUMEALL || !PLUTOPAK) - { - // prepare credits - M_CREDITS.title = M_CREDITS2.title = M_CREDITS3.title = s_Credits; - } - MenuEntry_HideOnCondition(&ME_MAIN_HELP, G_GetLogoFlags() & LOGO_NOHELP); -#ifndef EDUKE32_SIMPLE_MENU - MenuEntry_HideOnCondition(&ME_MAIN_CREDITS, G_GetLogoFlags() & LOGO_NOCREDITS); -#endif -} - -static void Menu_Run(Menu_t *cm, vec2_t origin); - - -static void Menu_BlackRectangle(int32_t x, int32_t y, int32_t width, int32_t height, int32_t orientation); - -/* -At present, no true difference is planned between Menu_Pre() and Menu_PreDraw(). -They are separate for purposes of organization. -*/ - -static void Menu_Pre(MenuID_t cm) -{ - int32_t i; - auto ps = g_player[myconnectindex].ps; - - switch (cm) - { - case MENU_MAIN_INGAME: - MenuEntry_DisableOnCondition(&ME_MAIN_SAVEGAME, ud.recstat == 2); - MenuEntry_DisableOnCondition(&ME_MAIN_QUITTOTITLE, g_netServer || numplayers > 1); - fallthrough__; - case MENU_MAIN: - if ((g_netServer || ud.multimode > 1) && ud.recstat != 2) - { - ME_MAIN_NEWGAME.entry = &MEO_MAIN_NEWGAME_NETWORK; - ME_MAIN_NEWGAME_INGAME.entry = &MEO_MAIN_NEWGAME_NETWORK; - } - else - { - ME_MAIN_NEWGAME.entry = &MEO_MAIN_NEWGAME; - ME_MAIN_NEWGAME_INGAME.entry = &MEO_MAIN_NEWGAME_INGAME; - } - break; - - case MENU_GAMESETUP: - MEO_GAMESETUP_DEMOREC.options = (ps->gm&MODE_GAME) ? &MEOS_DemoRec : &MEOS_OffOn; - MenuEntry_DisableOnCondition(&ME_GAMESETUP_DEMOREC, (ps->gm&MODE_GAME) && m_recstat != 1); - break; - - case MENU_DISPLAYSETUP: - MenuEntry_HideOnCondition(&ME_DISPLAYSETUP_VOXELS, !g_haveVoxels); -#ifdef USE_OPENGL - if (videoGetRenderMode() == REND_CLASSIC) - MenuMenu_ChangeEntryList(M_DISPLAYSETUP, MEL_DISPLAYSETUP); - else - MenuMenu_ChangeEntryList(M_DISPLAYSETUP, MEL_DISPLAYSETUP_GL); - - MEO_SCREENSETUP_SCREENSIZE.steps = !(ud.statusbarflags & STATUSBAR_NONONE) + - !(ud.statusbarflags & STATUSBAR_NOMODERN) + - !(ud.statusbarflags & STATUSBAR_NOMINI) + - !(ud.statusbarflags & STATUSBAR_NOOVERLAY) + - !(ud.statusbarflags & STATUSBAR_NOFULL) + - !(ud.statusbarflags & STATUSBAR_NOSHRINK) * 14; - MEO_SCREENSETUP_SCREENSIZE.max = MEO_SCREENSETUP_SCREENSIZE.steps - 1; - if (MEO_SCREENSETUP_SCREENSIZE.steps <= 2 && !(ud.statusbarflags & STATUSBAR_NONONE)) - { - ME_SCREENSETUP_SCREENSIZE.entry = &MEO_SCREENSETUP_SCREENSIZE_TWO; - ME_SCREENSETUP_SCREENSIZE.type = Option; - } - else - { - ME_SCREENSETUP_SCREENSIZE.entry = &MEO_SCREENSETUP_SCREENSIZE; - ME_SCREENSETUP_SCREENSIZE.type = RangeInt32; - } - MenuEntry_HideOnCondition(&ME_SCREENSETUP_SCREENSIZE, (MEO_SCREENSETUP_SCREENSIZE.steps < 2)); - - break; - - case MENU_POLYMER: - case MENU_POLYMOST: - MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_PRECACHE, !hw_hightile); - MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_DETAILTEX, !hw_hightile); - MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_GLOWTEX, !hw_hightile); -#endif - break; - - case MENU_VIDEOSETUP: - { - Bmemset(resolution, 0, sizeof(resolution)); - MEOS_VIDEOSETUP_RESOLUTION.numOptions = 0; - - // prepare video setup - for (int i = 0; i < validmodecnt; ++i) - { - int j; - - for (j = 0; j < MEOS_VIDEOSETUP_RESOLUTION.numOptions; ++j) - { - if (validmode[i].xdim == resolution[j].xdim && validmode[i].ydim == resolution[j].ydim) - { - resolution[j].flags |= validmode[i].fs ? RES_FS : RES_WIN; - Bsnprintf(resolution[j].name, MAXRESOLUTIONSTRINGLENGTH, "%d x %d%s", resolution[j].xdim, resolution[j].ydim, (resolution[j].flags & RES_FS) ? "" : "Win"); - MEOSN_VIDEOSETUP_RESOLUTION[j] = resolution[j].name; - if (validmode[i].bpp > resolution[j].bppmax) - resolution[j].bppmax = validmode[i].bpp; - break; - } - } - - if (j == MEOS_VIDEOSETUP_RESOLUTION.numOptions) // no match found - { - resolution[j].xdim = validmode[i].xdim; - resolution[j].ydim = validmode[i].ydim; - resolution[j].bppmax = validmode[i].bpp; - resolution[j].flags = validmode[i].fs ? RES_FS : RES_WIN; - Bsnprintf(resolution[j].name, MAXRESOLUTIONSTRINGLENGTH, "%d x %d%s", resolution[j].xdim, resolution[j].ydim, (resolution[j].flags & RES_FS) ? "" : "Win"); - MEOSN_VIDEOSETUP_RESOLUTION[j] = resolution[j].name; - ++MEOS_VIDEOSETUP_RESOLUTION.numOptions; - } - } - - const int32_t nr = newresolution; - - // don't allow setting fullscreen mode if it's not supported by the resolution - MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_FULLSCREEN, !(resolution[nr].flags & RES_FS)); - - MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_APPLY, - (xres == resolution[nr].xdim && yres == resolution[nr].ydim && - videoGetRenderMode() == newrendermode && fullscreen == newfullscreen - && vid_vsync == newvsync && r_borderless == newborderless - ) - || (newrendermode != REND_CLASSIC && resolution[nr].bppmax <= 8)); - MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_BORDERLESS, newfullscreen); - break; - } - - case MENU_SOUND: - case MENU_SOUND_INGAME: - case MENU_ADVSOUND: - MenuEntry_DisableOnCondition(&ME_SOUND_VOLUME_FX, !snd_enabled); - MenuEntry_DisableOnCondition(&ME_SOUND_VOLUME_MUSIC, !mus_enabled); - MenuEntry_DisableOnCondition(&ME_SOUND_DUKETALK, !snd_enabled); - MenuEntry_DisableOnCondition(&ME_SOUND_SAMPLINGRATE, !snd_enabled && !mus_enabled); -#ifndef EDUKE32_SIMPLE_MENU - MenuEntry_DisableOnCondition(&ME_SOUND_NUMVOICES, !snd_enabled); -#endif - MenuEntry_DisableOnCondition(&ME_SOUND_RESTART, soundrate == snd_mixrate && - soundvoices == snd_numvoices); - break; - - case MENU_SAVESETUP: - MenuEntry_DisableOnCondition(&ME_SAVESETUP_MAXAUTOSAVES, !cl_autosavedeletion); - break; - - case MENU_JOYSTICKSETUP: - MenuEntry_DisableOnCondition(&ME_JOYSTICK_EDITBUTTONS, !CONTROL_JoyPresent || (joystick.numButtons == 0 && joystick.numHats == 0)); - MenuEntry_DisableOnCondition(&ME_JOYSTICK_EDITAXES, !CONTROL_JoyPresent || joystick.numAxes == 0); - MenuEntry_DisableOnCondition(&ME_JOYSTICK_DEFAULTS_STANDARD, !joystick.isGameController); - MenuEntry_DisableOnCondition(&ME_JOYSTICK_DEFAULTS_PRO, !joystick.isGameController); - break; - -#ifndef EDUKE32_SIMPLE_MENU - case MENU_MOUSESETUP: - MenuEntry_DisableOnCondition(&ME_MOUSESETUP_MOUSEAIMING, in_aimmode); - break; -#endif - case MENU_NETOPTIONS: - if (MEOSV_NetEpisodes[MEO_NETOPTIONS_EPISODE.currentOption] == MAXVOLUMES) - MEL_NETOPTIONS[2] = &ME_NETOPTIONS_USERMAP; - else - { - MEL_NETOPTIONS[2] = &ME_NETOPTIONS_LEVEL; - MEO_NETOPTIONS_LEVEL.options = &MEOS_NETOPTIONS_LEVEL[MEOSV_NetEpisodes[MEO_NETOPTIONS_EPISODE.currentOption]]; - } - if (!(g_gametypeFlags[m_coop] & GAMETYPE_MARKEROPTION)) - { - ME_NETOPTIONS_MARKERS.type = Dummy; - ME_NETOPTIONS_MARKERS.flags |= MEF_Disabled; - } - else - { - ME_NETOPTIONS_MARKERS.type = Option; - ME_NETOPTIONS_MARKERS.flags &= ~MEF_Disabled; - } - MEL_NETOPTIONS[5] = (g_gametypeFlags[m_coop] & (GAMETYPE_PLAYERSFRIENDLY|GAMETYPE_TDM)) ? &ME_NETOPTIONS_FRFIRE : &ME_NETOPTIONS_MAPEXITS; - break; - - case MENU_OPTIONS: - MenuEntry_DisableOnCondition(&ME_OPTIONS_PLAYERSETUP, ud.recstat == 1); - break; - - case MENU_COLCORR: - case MENU_COLCORR_INGAME: - break; - - case MENU_CHEATS: - case MENU_CHEATENTRY: - case MENU_CHEAT_WARP: - case MENU_CHEAT_SKILL: - { - const int32_t menucheatsdisabled = numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME); - - // refresh display names of quote cheats - if (!DUKEBETA) - { - ME_CheatCodes[CHEATFUNC_QUOTEBETA].name = apStrings[QUOTE_CHEAT_BETA]; - if (!NAM) - ME_CheatCodes[CHEATFUNC_QUOTETODD].name = apStrings[QUOTE_CHEAT_TODD]; - ME_CheatCodes[CHEATFUNC_QUOTEALLEN].name = apStrings[QUOTE_CHEAT_ALLEN]; - } - - for (i = 0; i < NUMCHEATFUNCS; i++) - { - uint32_t cheatmask = cl_cheatmask & (1<>11),0,2+8); - } - break; - case MENU_PLAYER: - rotatesprite_fs(origin.x + (260<<16), origin.y + ((24+(tilesiz[APLAYER].y>>1))<<16), 49152L,0,1441-((((4-((int32_t) totalclock>>4)))&3)*5),0,entry == &ME_PLAYER_TEAM ? G_GetTeamPalette(playerteam) : playercolor,10); - break; - - case MENU_MACROS: - mgametextcenter(origin.x, origin.y + (144<<16), "Activate in-game with Shift-F#"); - break; - - case MENU_COLCORR: - case MENU_COLCORR_INGAME: - // center panel - rotatesprite_fs(origin.x + (120<<16), origin.y + (32<<16), 16384, 0, 3290, 0, 0, 2|8|16); - rotatesprite_fs(origin.x + (160<<16) - (tilesiz[BOTTOMSTATUSBAR].x<<13), origin.y + (82<<16) - (tilesiz[BOTTOMSTATUSBAR].y<<14), 16384, 0, BOTTOMSTATUSBAR, 0, 0, 2|8|16); - - // left panel - rotatesprite_fs(origin.x + (40<<16), origin.y + (32<<16), 16384, 0, BONUSSCREEN, 0, 0, 2|8|16); - - // right panel - rotatesprite_fs(origin.x + (200<<16), origin.y + (32<<16), 16384, 0, LOADSCREEN, 0, 0, 2|8|16); - break; - - case MENU_NETSETUP: - case MENU_NETHOST: - mminitext(origin.x + (90<<16), origin.y + (90<<16), "Game Type", MF_Minifont.pal_deselected); - mminitext(origin.x + (90<<16), origin.y + ((90+8)<<16), "Episode", MF_Minifont.pal_deselected); - mminitext(origin.x + (90<<16), origin.y + ((90+8+8)<<16), "Level", MF_Minifont.pal_deselected); - mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8)<<16), ME_NETOPTIONS_MONSTERS.name, MF_Minifont.pal_deselected); - if (m_coop == 0) - mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8)<<16), "Markers", MF_Minifont.pal_deselected); - else if (m_coop == 1) - mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8)<<16), "Friendly Fire", MF_Minifont.pal_deselected); - mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8+8)<<16), "User Map", MF_Minifont.pal_deselected); - - mminitext(origin.x + ((90+60)<<16), origin.y + (90<<16), g_gametypeNames[m_coop], MF_Minifont.pal_deselected_right); - - mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8)<<16), g_volumeNames[ud.m_volume_number], MF_Minifont.pal_deselected_right); - mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8)<<16), g_mapInfo[MAXLEVELS*ud.m_volume_number+m_level_number].name, MF_Minifont.pal_deselected_right); - if (ud.m_monsters_off == 0 || ud.m_player_skill > 0) - mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), g_skillNames[ud.m_player_skill], MF_Minifont.pal_deselected_right); - else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), "None", MF_Minifont.pal_deselected_right); - if (m_coop == 0) - { - if (m_marker) mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "On", MF_Minifont.pal_deselected_right); - else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "Off", MF_Minifont.pal_deselected_right); - } - else if (m_coop == 1) - { - if (m_ffire) mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "On", MF_Minifont.pal_deselected_right); - else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "Off", MF_Minifont.pal_deselected_right); - } - break; - - case MENU_RESETPLAYER: - videoFadeToBlack(1); - Bsprintf(tempbuf, "Load last game:\n\"%s\"", g_quickload->name); - Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); - break; - - case MENU_LOAD: - { -#if 0 - for (i = 0; i <= 108; i += 12) - rotatesprite_fs(origin.x + ((160+64+91-64)<<16), origin.y + ((i+56)<<16), 65536L,0,TEXTBOX,24,0,10); -#endif - Menu_BlackRectangle(origin.x + (198<<16), origin.y + (47<<16), 102<<16, 100<<16, 1|32); - - rotatesprite_fs(origin.x + (22<<16), origin.y + (97<<16), 65536L,0,WINDOWBORDER2,24,0,10); - rotatesprite_fs(origin.x + (180<<16), origin.y + (97<<16), 65536L,1024,WINDOWBORDER2,24,0,10); - rotatesprite_fs(origin.x + (99<<16), origin.y + (50<<16), 65536L,512,WINDOWBORDER1,24,0,10); - rotatesprite_fs(origin.x + (103<<16), origin.y + (144<<16), 65536L,1024+512,WINDOWBORDER1,24,0,10); - - if (M_LOAD.currentEntry >= (int32_t)g_nummenusaves) - { - menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "Empty"); - break; - } - - menusave_t & msv = g_menusaves[M_LOAD.currentEntry]; - - if (msv.brief.isValid()) - { - if (tilePtr(TILE_LOADSHOT)) - rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536>>1,512,TILE_LOADSHOT, msv.isOldVer?16:-32, 0,4+10+64); - - if (msv.isOldVer) - { - mgametextcenterat(origin.x + (101<<16), origin.y + (50<<16), - msv.brief.isExt ? "Previous Version,\nSequence Point Available" : "Previous Version,\nUnable to Load"); - -#ifndef EDUKE32_SIMPLE_MENU - Bsprintf(tempbuf,"Saved: %d.%d.%d.%u %d-bit", savehead.majorver, savehead.minorver, - savehead.bytever, savehead.userbytever, 8*savehead.getPtrSize()); - mgametext(origin.x + (25<<16), origin.y + (124<<16), tempbuf); - Bsprintf(tempbuf,"Our: %d.%d.%d.%u %d-bit", SV_MAJOR_VER, SV_MINOR_VER, BYTEVERSION, - ud.userbytever, (int32_t)(8*sizeof(intptr_t))); - mgametext(origin.x + ((25+16)<<16), origin.y + (134<<16), tempbuf); -#endif - - if (msv.isUnreadable) - break; - } - - if (savehead.numplayers > 1) - { - Bsprintf(tempbuf, "Players: %-2d ", savehead.numplayers); - mgametextcenter(origin.x, origin.y + (156<<16), tempbuf); - } - - { - const char *name = g_mapInfo[(savehead.volnum*MAXLEVELS) + savehead.levnum].name; - Bsprintf(tempbuf, "%s / %s", name ? name : "^10unnamed^0", g_skillNames[savehead.skill-1]); - } - - mgametextcenter(origin.x, origin.y + (168<<16), tempbuf); - if (savehead.volnum == 0 && savehead.levnum == 7) - mgametextcenter(origin.x, origin.y + (180<<16), savehead.boardfn); - } - break; - } - - case MENU_SAVE: - { -#if 0 - for (i = 0; i <= 108; i += 12) - rotatesprite_fs(origin.x + ((160+64+91-64)<<16), origin.y + ((i+56)<<16), 65536L,0,TEXTBOX,24,0,10); -#endif - Menu_BlackRectangle(origin.x + (198<<16), origin.y + (47<<16), 102<<16, 100<<16, 1|32); - - rotatesprite_fs(origin.x + (22<<16), origin.y + (97<<16), 65536L,0,WINDOWBORDER2,24,0,10); - rotatesprite_fs(origin.x + (180<<16), origin.y + (97<<16), 65536L,1024,WINDOWBORDER2,24,0,10); - rotatesprite_fs(origin.x + (99<<16), origin.y + (50<<16), 65536L,512,WINDOWBORDER1,24,0,10); - rotatesprite_fs(origin.x + (103<<16), origin.y + (144<<16), 65536L,1024+512,WINDOWBORDER1,24,0,10); - - j = 0; - for (int k = 0; k < g_nummenusaves+1; ++k) - if (((MenuString_t*)M_SAVE.entrylist[k]->entry)->editfield) - j |= 1; - - if (j) - rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536L>>1,512,TILE_SAVESHOT,-32,0,4+10+64); - else if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves) - { - menusave_t & msv = g_menusaves[M_SAVE.currentEntry-1]; - - if (msv.brief.isValid()) - { - if (tilePtr(TILE_LOADSHOT)) - rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536>>1,512,TILE_LOADSHOT, msv.isOldVer?16:-32, 0,4+10+64); - - if (msv.isOldVer) - { - mgametextcenterat(origin.x + (101<<16), origin.y + (50<<16), - msv.brief.isExt ? "Previous Version,\nSequence Point Available" : "Previous Version,\nUnable to Load"); - -#ifndef EDUKE32_SIMPLE_MENU - Bsprintf(tempbuf,"Saved: %d.%d.%d.%u %d-bit", savehead.majorver, savehead.minorver, - savehead.bytever, savehead.userbytever, 8*savehead.getPtrSize()); - mgametext(origin.x + (25<<16), origin.y + (124<<16), tempbuf); - Bsprintf(tempbuf,"Our: %d.%d.%d.%u %d-bit", SV_MAJOR_VER, SV_MINOR_VER, BYTEVERSION, - ud.userbytever, (int32_t)(8*sizeof(intptr_t))); - mgametext(origin.x + ((25+16)<<16), origin.y + (134<<16), tempbuf); -#endif - } - } - } - else - menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "New"); - - if (ud.multimode > 1) - { - Bsprintf(tempbuf, "Players: %-2d ", ud.multimode); - mgametextcenter(origin.x, origin.y + (156<<16), tempbuf); - } - - Bsprintf(tempbuf,"%s / %s",g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]); - mgametextcenter(origin.x, origin.y + (168<<16), tempbuf); - if (ud.volume_number == 0 && ud.level_number == 7) - mgametextcenter(origin.x, origin.y + (180<<16), currentboardfilename); - break; - } - -#ifdef EDUKE32_ANDROID_MENU - case MENU_SKILL: - { - static const char *s[] = { "EASY - Few enemies, and lots of stuff.", "MEDIUM - Normal difficulty.", "HARD - For experienced players.", "EXPERTS - Lots of enemies, plus they respawn!" }; - if (M_SKILL.currentEntry < ARRAY_SSIZE(s)) - mgametextcenter(origin.x, origin.y + (168<<16), s[M_SKILL.currentEntry]); - } - break; -#endif - - case MENU_SAVECLEANVERIFY: - videoFadeToBlack(1); - - if (g_oldSaveCnt) - { - Bsprintf(tempbuf, "Delete %d obsolete saves?\nThis action cannot be undone.", g_oldSaveCnt); - Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); - } - else - mgametextcenter(origin.x, origin.y + (90<<16), "No obsolete saves found!"); - - break; - - case MENU_LOADVERIFY: - { - videoFadeToBlack(1); - menusave_t & msv = g_menusaves[M_LOAD.currentEntry]; - if (msv.isOldVer && msv.brief.isExt) - { - Bsprintf(tempbuf, "Resume game from sequence point:\n\"%s\"", msv.brief.name); - Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); - } - else if (msv.isOldVer) - { -#if 1 - mgametextcenter(origin.x, origin.y + (90<<16), "You're not supposed to be here."); -#else - Bsprintf(tempbuf, "Start new game:\n%s / %s" - , g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]); - Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); -#endif - } - else - { - Bsprintf(tempbuf, "Load game:\n\"%s\"", msv.brief.name); - Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); - } - break; - } - - case MENU_SAVEVERIFY: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Overwrite previous saved game?"); - break; - - case MENU_LOADDELVERIFY: - case MENU_SAVEDELVERIFY: - { - videoFadeToBlack(1); - menusave_t & msv = cm == MENU_LOADDELVERIFY ? g_menusaves[M_LOAD.currentEntry] : g_menusaves[M_SAVE.currentEntry-1]; - Bsprintf(tempbuf, "Delete saved game:\n\"%s\"?", msv.brief.name); - Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); - break; - } - - case MENU_NEWVERIFY: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Abort this game?"); - break; - - case MENU_COLCORRRESETVERIFY: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Reset color correction to defaults?"); - break; - case MENU_KEYSRESETVERIFY: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Reset keys to defaults?"); - break; - case MENU_KEYSCLASSICVERIFY: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Reset keys to classic defaults?"); - break; - case MENU_JOYSTANDARDVERIFY: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Reset gamepad to standard layout?"); - break; - case MENU_JOYPROVERIFY: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Reset gamepad to pro layout?"); - break; - case MENU_JOYCLEARVERIFY: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Clear all gamepad settings?"); - break; - - case MENU_QUIT: - case MENU_QUIT_INGAME: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "Are you sure you want to quit?"); - break; - - case MENU_QUITTOTITLE: - videoFadeToBlack(1); - Menu_DrawVerifyPrompt(origin.x, origin.y, "End game and return to title screen?"); - break; - - case MENU_NETWAITMASTER: - G_DrawFrags(); - mgametextcenter(origin.x, origin.y + (50<<16), "Waiting for master\n" - "to select level"); - break; - - case MENU_NETWAITVOTES: - G_DrawFrags(); - mgametextcenter(origin.x, origin.y + (90<<16), "Waiting for votes"); - break; - -#ifndef EDUKE32_STANDALONE - case MENU_BUYDUKE: - mgametextcenter(origin.x, origin.y + (33<<16), "You are playing the shareware\n" - "version of Duke Nukem 3D. While\n" - "this version is really cool, you\n" - "are missing over 75% of the total\n" - "game, along with other great extras\n" - "which you'll get when you order\n" - "the complete version and get\n" - "the final three episodes."); - - mgametextcenter(origin.x, origin.y + ((148+16)<<16), "Press any key or button..."); - break; -#endif - case MENU_CREDITS: - case MENU_CREDITS2: - case MENU_CREDITS3: -#ifndef EDUKE32_STANDALONE - if (!VOLUMEALL || !PLUTOPAK) - { - int32_t m; - switch (cm) - { - case MENU_CREDITS: - m = origin.x + (20<<16); - l = origin.y + (33<<16); - - shadowminitext(m, l, "Original Concept", 12); l += 7<<16; - shadowminitext(m, l, "Todd Replogle and Allen H. Blum III", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Produced & Directed By", 12); l += 7<<16; - shadowminitext(m, l, "Greg Malone", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Executive Producer", 12); l += 7<<16; - shadowminitext(m, l, "George Broussard", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "BUILD Engine", 12); l += 7<<16; - shadowminitext(m, l, "Ken Silverman", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Game Programming", 12); l += 7<<16; - shadowminitext(m, l, "Todd Replogle", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "3D Engine/Tools/Net", 12); l += 7<<16; - shadowminitext(m, l, "Ken Silverman", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Network Layer/Setup Program", 12); l += 7<<16; - shadowminitext(m, l, "Mark Dochtermann", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Map Design", 12); l += 7<<16; - shadowminitext(m, l, "Allen H. Blum III", 12); l += 7<<16; - shadowminitext(m, l, "Richard Gray", 12); l += 7<<16; - - m = origin.x + (180<<16); - l = origin.y + (33<<16); - - shadowminitext(m, l, "3D Modeling", 12); l += 7<<16; - shadowminitext(m, l, "Chuck Jones", 12); l += 7<<16; - shadowminitext(m, l, "Sapphire Corporation", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Artwork", 12); l += 7<<16; - shadowminitext(m, l, "Dirk Jones, Stephen Hornback", 12); l += 7<<16; - shadowminitext(m, l, "James Storey, David Demaret", 12); l += 7<<16; - shadowminitext(m, l, "Douglas R. Wood", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Sound Engine", 12); l += 7<<16; - shadowminitext(m, l, "Jim Dose", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Sound & Music Development", 12); l += 7<<16; - shadowminitext(m, l, "Robert Prince", 12); l += 7<<16; - shadowminitext(m, l, "Lee Jackson", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Voice Talent", 12); l += 7<<16; - shadowminitext(m, l, "Lani Minella - Voice Producer", 12); l += 7<<16; - shadowminitext(m, l, "Jon St. John as \"Duke Nukem\"", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Graphic Design", 12); l += 7<<16; - shadowminitext(m, l, "Packaging, Manual, Ads", 12); l += 7<<16; - shadowminitext(m, l, "Robert M. Atkins", 12); l += 7<<16; - shadowminitext(m, l, "Michael Hadwin", 12); l += 7<<16; - break; - - case MENU_CREDITS2: - m = origin.x + (20<<16); - l = origin.y + (33<<16); - - shadowminitext(m, l, "Special Thanks To", 12); l += 7<<16; - shadowminitext(m, l, "Steven Blackburn, Tom Hall", 12); l += 7<<16; - shadowminitext(m, l, "Scott Miller, Joe Siegler", 12); l += 7<<16; - shadowminitext(m, l, "Terry Nagy, Colleen Compton", 12); l += 7<<16; - shadowminitext(m, l, "HASH, Inc., FormGen, Inc.", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "The 3D Realms Beta Testers", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Nathan Anderson, Wayne Benner", 12); l += 7<<16; - shadowminitext(m, l, "Glenn Brensinger, Rob Brown", 12); l += 7<<16; - shadowminitext(m, l, "Erik Harris, Ken Heckbert", 12); l += 7<<16; - shadowminitext(m, l, "Terry Herrin, Greg Hively", 12); l += 7<<16; - shadowminitext(m, l, "Hank Leukart, Eric Baker", 12); l += 7<<16; - shadowminitext(m, l, "Jeff Rausch, Kelly Rogers", 12); l += 7<<16; - shadowminitext(m, l, "Mike Duncan, Doug Howell", 12); l += 7<<16; - shadowminitext(m, l, "Bill Blair", 12); l += 7<<16; - - m = origin.x + (160<<16); - l = origin.y + (33<<16); - - shadowminitext(m, l, "Company Product Support", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "The following companies were cool", 12); l += 7<<16; - shadowminitext(m, l, "enough to give us lots of stuff", 12); l += 7<<16; - shadowminitext(m, l, "during the making of Duke Nukem 3D.", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Altec Lansing Multimedia", 12); l += 7<<16; - shadowminitext(m, l, "for tons of speakers and the", 12); l += 7<<16; - shadowminitext(m, l, "THX-licensed sound system.", 12); l += 7<<16; - shadowminitext(m, l, "For info call 1-800-548-0620", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Creative Labs, Inc.", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Thanks for the hardware, guys.", 12); l += 7<<16; - break; - - case MENU_CREDITS3: - mgametextcenter(origin.x, origin.y + (50<<16), "Duke Nukem 3D is a trademark of\n" - "3D Realms Entertainment" - "\n" - "Duke Nukem 3D\n" - "(C) 1996 3D Realms Entertainment"); - -#if !defined(EDUKE32_ANDROID_MENU) && !defined(EDUKE32_STANDALONE) - if (VOLUMEONE) - { - mgametextcenter(origin.x, origin.y + (106<<16), "Please read LICENSE.DOC for shareware\n" - "distribution grants and restrictions."); - } -#endif - mgametextcenter(origin.x, origin.y + ((VOLUMEONE?134:115)<<16), "Made in Dallas, Texas USA"); - break; - } - } - break; -#endif case MENU_CREDITS4: // JBF 20031220 { #define MENU_YOFFSET 40 @@ -2696,385 +193,12 @@ static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin) } -static void Menu_ReadSaveGameHeaders(); - -static void Menu_LoadReadHeaders() -{ - Menu_ReadSaveGameHeaders(); - - for (int i = 0; i < g_nummenusaves; ++i) - { - menusave_t const & msv = g_menusaves[i]; - // MenuEntry_LookDisabledOnCondition(&ME_LOAD[i], msv.isOldVer && msv.brief.isExt); - MenuEntry_DisableOnCondition(&ME_LOAD[i], msv.isOldVer && !msv.brief.isExt); - } -} - -static void Menu_SaveReadHeaders() -{ - Menu_ReadSaveGameHeaders(); - - for (int i = 0; i < g_nummenusaves; ++i) - { - menusave_t const & msv = g_menusaves[i]; - MenuEntry_LookDisabledOnCondition(&ME_SAVE[i], msv.isOldVer && !msv.brief.isExt); - } -} - -static void Menu_PreInput(MenuEntry_t *entry) -{ - switch (g_currentMenu) - { - - case MENU_KEYBOARDKEYS: - if (inputState.GetKeyStatus(sc_Delete)) - { - Bindings.UnbindACommand(buttonMap.GetButtonName(M_KEYBOARDKEYS.currentEntry)); - S_PlaySound(KICK_HIT); - inputState.ClearKeyStatus(sc_Delete); - } - break; - - case MENU_LOAD: - if (inputState.GetKeyStatus(sc_Delete)) - { - inputState.ClearKeyStatus(sc_Delete); - if (M_LOAD.currentEntry < g_nummenusaves) - Menu_Change(MENU_LOADDELVERIFY); - } - break; - case MENU_SAVE: - if (inputState.GetKeyStatus(sc_Delete)) - { - inputState.ClearKeyStatus(sc_Delete); - if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves) - Menu_Change(MENU_SAVEDELVERIFY); - } - break; - - default: - break; - } -} - -static void Menu_PreOptionListDraw(MenuEntry_t *entry, const vec2_t origin) -{ - switch (g_currentMenu) - { - case MENU_MOUSEBTNS: - case MENU_MOUSEADVANCED: - case MENU_JOYSTICKBTNS: - case MENU_JOYSTICKAXIS: - mgametextcenter(origin.x, origin.y + (31<<16), "Select a function to assign"); - - Bsprintf(tempbuf, "to %s", entry->name); - - mgametextcenter(origin.x, origin.y + ((31+9)<<16), tempbuf); - - mgametextcenter(origin.x, origin.y + (161<<16), "Press \"Escape\" To Cancel"); - break; - } -} - -static int32_t Menu_PreCustom2ColScreen(MenuEntry_t *entry) -{ - if (g_currentMenu == MENU_KEYBOARDKEYS) - { - auto column = (MenuCustom2Col_t*)entry->entry; - - int32_t sc = inputState.GetLastScanCode(); - if (sc != sc_None) - { - S_PlaySound(PISTOL_BODYHIT); - Bindings.SetBind(sc, buttonMap.GetButtonName(M_KEYBOARDKEYS.currentEntry)); - inputState.ClearKeyStatus(sc); - - return -1; - } - } - - return 0; -} - -static void Menu_PreCustom2ColScreenDraw(MenuEntry_t *entry, const vec2_t origin) -{ - if (g_currentMenu == MENU_KEYBOARDKEYS) - { - Bsprintf(tempbuf, "Press the key to assign as\n" - "%s for \"%s\"\n" - "\n" - "Press \"Escape\" To Cancel" - , M_KEYBOARDKEYS.currentColumn?"secondary":"primary", entry->name); - mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); - } -} - -static void Menu_EntryFocus(/*MenuEntry_t *entry*/) -{ - switch (g_currentMenu) - { - case MENU_LOAD: - if (M_LOAD.currentEntry < (int32_t)g_nummenusaves) - { - savebrief_t & sv = g_menusaves[M_LOAD.currentEntry].brief; - if (sv.isValid()) - G_LoadSaveHeaderNew(sv.path, &savehead); - } - break; - - case MENU_SAVE: - if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves) - { - savebrief_t & sv = g_menusaves[M_SAVE.currentEntry-1].brief; - if (sv.isValid()) - G_LoadSaveHeaderNew(sv.path, &savehead); - } - break; - - default: - break; - } -} - -static void Menu_StartGameWithoutSkill(void) -{ - ud.m_player_skill = M_SKILL.currentEntry+1; - - ud.skill_voice = S_PlaySound(PISTOL_BODYHIT); - - ud.m_respawn_monsters = 0; - - ud.m_monsters_off = ud.monsters_off = 0; - - ud.m_respawn_items = 0; - ud.m_respawn_inventory = 0; - - ud.multimode = 1; - - G_NewGame_EnterLevel(); -} - -static void Menu_DoCheat(int32_t cheatID) -{ - if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME)) - return; - - osdcmd_cheatsinfo_stat.cheatnum = cheatID; -} - -static int32_t Menu_Cheat_Warp(char const * const numbers) -{ - if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME)) - return 0; - - if (numbers == NULL || !numbers[0] || !numbers[1] || (VOLUMEALL && !numbers[2])) - return 1; - - if (VOLUMEALL) - { - osdcmd_cheatsinfo_stat.volume = numbers[0] - '0'; - osdcmd_cheatsinfo_stat.level = (numbers[1] - '0')*10+(numbers[2]-'0'); - } - else - { - osdcmd_cheatsinfo_stat.volume = numbers[0] - '0'; - osdcmd_cheatsinfo_stat.level = numbers[1] - '0'; - } - - osdcmd_cheatsinfo_stat.volume--; - osdcmd_cheatsinfo_stat.level--; - - if ((VOLUMEONE && osdcmd_cheatsinfo_stat.volume > 0) || osdcmd_cheatsinfo_stat.volume > g_volumeCnt-1 || - osdcmd_cheatsinfo_stat.level >= MAXLEVELS || g_mapInfo[osdcmd_cheatsinfo_stat.volume *MAXLEVELS+osdcmd_cheatsinfo_stat.level].filename == NULL) - return 1; - - osdcmd_cheatsinfo_stat.cheatnum = CHEAT_SCOTTY; - - return 0; -} - -static int32_t Menu_Cheat_Skill(char const * const number) -{ - if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME)) - return 0; - - if (number == NULL || !number[0]) - return 1; - - osdcmd_cheatsinfo_stat.volume = number[0] - '1'; - - osdcmd_cheatsinfo_stat.cheatnum = CHEAT_SKILL; - - return 0; -} - /* Functions where a "newValue" or similar is passed are run *before* the linked variable is actually changed. That way you can compare the new and old values and potentially block the change. */ static void Menu_EntryLinkActivate(MenuEntry_t *entry) { - switch (g_currentMenu) - { - case MENU_EPISODE: - if (entry != &ME_EPISODE_USERMAP) - { - ud.m_volume_number = M_EPISODE.currentEntry; - m_level_number = 0; - - if (g_skillCnt == 0) - Menu_StartGameWithoutSkill(); - } - break; - - case MENU_NEWGAMECUSTOM: - ud.returnvar[0] = -1; - VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, M_NEWGAMECUSTOM.currentEntry); - break; - - case MENU_NEWGAMECUSTOMSUB: - ud.returnvar[0] = M_NEWGAMECUSTOMSUB.currentEntry; - ud.returnvar[1] = -1; - VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, M_NEWGAMECUSTOM.currentEntry); - break; - - case MENU_SKILL: - { - int32_t skillsound = PISTOL_BODYHIT; - - switch (M_SKILL.currentEntry) - { - case 0: - skillsound = JIBBED_ACTOR6; - break; - case 1: - skillsound = BONUS_SPEECH1; - break; - case 2: - skillsound = DUKE_GETWEAPON2; - break; - case 3: - skillsound = JIBBED_ACTOR5; - break; - } - - ud.m_player_skill = M_SKILL.currentEntry+1; - - ud.skill_voice = S_PlaySound(skillsound); - - if (M_SKILL.currentEntry == 3) ud.m_respawn_monsters = 1; - else ud.m_respawn_monsters = 0; - - ud.m_monsters_off = ud.monsters_off = 0; - - ud.m_respawn_items = 0; - ud.m_respawn_inventory = 0; - - ud.multimode = 1; - - G_NewGame_EnterLevel(); - break; - } - - case MENU_JOYSTICKAXES: - M_JOYSTICKAXIS.title = joyGetName(0, M_JOYSTICKAXES.currentEntry); -#if 0 - MEO_JOYSTICKAXIS_ANALOG.data = &JoystickAnalogueAxes[M_JOYSTICKAXES.currentEntry]; - MEO_JOYSTICKAXIS_SCALE.variable = &JoystickAnalogueScale[M_JOYSTICKAXES.currentEntry]; - MEO_JOYSTICKAXIS_INVERT.data = &JoystickAnalogueInvert[M_JOYSTICKAXES.currentEntry]; - MEO_JOYSTICKAXIS_DEAD.variable = &JoystickAnalogueDead[M_JOYSTICKAXES.currentEntry]; - MEO_JOYSTICKAXIS_SATU.variable = &JoystickAnalogueSaturate[M_JOYSTICKAXES.currentEntry]; -#endif - break; - - case MENU_CHEATS: - { - const int32_t cheatFuncID = M_CHEATS.currentEntry - 1; - switch (cheatFuncID) - { - case -1: - case CHEATFUNC_WARP: - case CHEATFUNC_SKILL: - break; - default: - Menu_DoCheat(CheatFunctionIDs[cheatFuncID]); - break; - } - break; - } - - default: - break; - } - - if (entry == &ME_VIDEOSETUP_APPLY) - { - resolution_t p = { xres, yres, fullscreen, bpp, 0 }; - int32_t prend = videoGetRenderMode(); - int32_t pvsync = vid_vsync; - int pborderless = r_borderless; - - resolution_t n = { resolution[newresolution].xdim, resolution[newresolution].ydim, - (resolution[newresolution].flags & RES_FS) ? newfullscreen : 0, - (newrendermode == REND_CLASSIC) ? 8 : resolution[newresolution].bppmax, 0 }; - - if (r_borderless != newborderless) - videoResetMode(); - - r_borderless = newborderless; - - if (videoSetGameMode(n.flags, n.xdim, n.ydim, n.bppmax, upscalefactor) < 0) - { - r_borderless = pborderless; - - if (videoSetGameMode(p.flags, p.xdim, p.ydim, p.bppmax, upscalefactor) < 0) - { - videoSetRenderMode(prend); - G_GameExit("Failed restoring old video mode."); - } - else - { - onvideomodechange(p.bppmax > 8); - vid_vsync = videoSetVsync(pvsync); - } - } - else - { - videoSetRenderMode(newrendermode); - vid_vsync = videoSetVsync(newvsync); - onvideomodechange(n.bppmax > 8); - } - - g_restorePalette = -1; - G_UpdateScreenArea(); - ScreenMode = fullscreen; - ScreenWidth = xres; - ScreenHeight = yres; - ScreenBPP = bpp; - } - else if (entry == &ME_SOUND_RESTART) - { - snd_mixrate = soundrate; - snd_numvoices = soundvoices; - mus_device = musicdevice; - - S_SoundShutdown(); - S_MusicShutdown(); - - S_SoundStartup(); - S_MusicStartup(); - - FX_StopAllSounds(); - S_ClearSoundLocks(); - - if (MusicEnabled()) - S_RestartMusic(); - } - else if (entry == &ME_SAVESETUP_CLEANUP) - { - g_oldSaveCnt = G_CountOldSaves(); - Menu_Change(MENU_SAVECLEANVERIFY); - } else if (entry == &ME_NETHOST_LAUNCH) { // master does whatever it wants @@ -3092,3920 +216,10 @@ static void Menu_EntryLinkActivate(MenuEntry_t *entry) } } -static int32_t Menu_EntryOptionModify(MenuEntry_t *entry, int32_t newOption) -{ - int32_t x; - auto ps = g_player[myconnectindex].ps; - if (entry == &ME_GAMESETUP_DEMOREC) - { - if ((ps->gm&MODE_GAME)) - G_CloseDemoWrite(); - } - else if (entry == &ME_GAMESETUP_WEAPSWITCH_PICKUP) - { - ud.weaponswitch = ud.weaponswitch & ~(1|4); - switch (newOption) - { - case 2: - ud.weaponswitch = ud.weaponswitch | 4; - fallthrough__; - case 1: - ud.weaponswitch = ud.weaponswitch | 1; - break; - default: - break; - } - } - else if (entry == &ME_SOUND) - { - if (newOption == 0) - { - FX_StopAllSounds(); - S_ClearSoundLocks(); - } - } - else if (entry == &ME_SOUND_MUSIC) - { - mus_enabled = newOption; - if (newOption == 0) - S_PauseMusic(true); - else - { - S_RestartMusic(); - S_PauseMusic(false); - } - } - else if (entry == &ME_SOUND_DUKETALK) - snd_speech = (snd_speech&~1) | newOption; - else if (entry == &ME_JOYSTICK_ENABLE) - { - if (newOption) - CONTROL_ScanForControllers(); - CONTROL_JoystickEnabled = (newOption && CONTROL_JoyPresent); - } - else if (entry == &ME_JOYSTICKAXIS_ANALOG) - CONTROL_MapAnalogAxis(M_JOYSTICKAXES.currentEntry, newOption, controldevice_joystick); - else if (entry == &ME_JOYSTICKAXIS_INVERT) - CONTROL_SetAnalogAxisInvert(M_JOYSTICKAXES.currentEntry, newOption, controldevice_joystick); - else if (entry == &ME_NETOPTIONS_EPISODE) - { - if (newOption < g_volumeCnt) - ud.m_volume_number = newOption; - } - else if (entry == &ME_NETOPTIONS_MONSTERS) - { - ud.m_monsters_off = (newOption == g_skillCnt); - if (newOption < g_skillCnt) - ud.m_player_skill = newOption; - } - else if (entry == &ME_ADULTMODE) - { - if (newOption) - { - for (x=0; x8); - G_RefreshLights(); - } -#endif -} - -static void Menu_Custom2ColScreen(/*MenuEntry_t *entry*/) -{ - if (g_currentMenu == MENU_KEYBOARDKEYS) - { - inputState.keyFlushChars(); - inputState.ClearLastScanCode(); - } -} - -static int32_t Menu_EntryRangeInt32Modify(MenuEntry_t *entry, int32_t newValue) -{ - if (entry == &ME_SCREENSETUP_SBARSIZE) - G_SetStatusBarScale(newValue); - else if (entry == &ME_SOUND_VOLUME_FX) - FX_SetVolume(newValue); - else if (entry == &ME_SOUND_VOLUME_MUSIC) - S_MusicVolume(newValue); - else if (entry == &ME_JOYSTICKAXIS_SCALE) - CONTROL_SetAnalogAxisScale(M_JOYSTICKAXES.currentEntry, newValue, controldevice_joystick); - else if (entry == &ME_JOYSTICKAXIS_DEAD) - joySetDeadZone(M_JOYSTICKAXES.currentEntry, newValue, *MEO_JOYSTICKAXIS_SATU.cVar); - else if (entry == &ME_JOYSTICKAXIS_SATU) - joySetDeadZone(M_JOYSTICKAXES.currentEntry, *MEO_JOYSTICKAXIS_DEAD.cVar, newValue); - - return 0; -} - -static int32_t Menu_EntryRangeFloatModify(MenuEntry_t *entry, float newValue) -{ -#ifndef EDUKE32_SIMPLE_MENU - if (entry == &ME_COLCORR_AMBIENT) - r_ambientlightrecip = 1.f/newValue; -#else - UNREFERENCED_PARAMETER(entry); - UNREFERENCED_PARAMETER(newValue); -#endif - - return 0; -} - -static int32_t Menu_EntryRangeFloatDidModify(MenuEntry_t *entry) -{ - return 0; -} - -#ifdef MENU_ENABLE_RANGEDOUBLE -static int32_t Menu_EntryRangeDoubleModify(void /*MenuEntry_t *entry, double newValue*/) -{ - - return 0; -} -#endif - -static uint32_t save_xxh = 0; - -static void Menu_EntryStringActivate(/*MenuEntry_t *entry*/) -{ - switch (g_currentMenu) - { - case MENU_SAVE: - if (M_SAVE.currentEntry > 0) - { - savebrief_t & sv = g_menusaves[M_SAVE.currentEntry-1].brief; - if (!save_xxh) - save_xxh = SuperFastHash(sv.name, MAXSAVEGAMENAME); - if (sv.isValid()) - Menu_Change(MENU_SAVEVERIFY); - } - else - { - ME_SAVE_NEW.name = nullptr; - save_xxh = 0; - } - break; - - default: - break; - } -} - -static int32_t Menu_EntryStringSubmit(/*MenuEntry_t *entry, */char *input) -{ - int32_t returnvar = 0; - - switch (g_currentMenu) - { - case MENU_SAVE: - { - savebrief_t & sv = g_lastusersave = M_SAVE.currentEntry == 0 ? savebrief_t{input} : g_menusaves[M_SAVE.currentEntry-1].brief; - - // dirty hack... char 127 in last position indicates an auto-filled name -#ifdef __ANDROID__ - if (1) -#else - if (input[0] == 0 || (sv.name[MAXSAVEGAMENAME] == 127 && - strncmp(sv.name, input, MAXSAVEGAMENAME) == 0 && - save_xxh == SuperFastHash(sv.name, MAXSAVEGAMENAME))) -#endif - { - strncpy(sv.name, g_mapInfo[ud.volume_number * MAXLEVELS + ud.level_number].name, MAXSAVEGAMENAME); - sv.name[MAXSAVEGAMENAME] = 127; - returnvar = -1; - } - else - { - strncpy(sv.name, input, MAXSAVEGAMENAME); - sv.name[MAXSAVEGAMENAME] = 0; - } - - G_SavePlayerMaybeMulti(sv); - - g_quickload = &sv; - g_player[myconnectindex].ps->gm = MODE_GAME; - - Menu_Change(MENU_CLOSE); - save_xxh = 0; - break; - } - - default: - break; - } - - return returnvar; -} - -static void Menu_EntryStringCancel(/*MenuEntry_t *entry*/) -{ - switch (g_currentMenu) - { - case MENU_SAVE: - save_xxh = 0; - ME_SAVE_NEW.name = s_NewSaveGame; - break; - - default: - break; - } -} - -/* -This is polled when the menu code is populating the screen but for some reason doesn't have the data. -*/ -static int32_t Menu_EntryOptionSource(MenuEntry_t *entry, int32_t currentValue) -{ - if (entry == &ME_GAMESETUP_WEAPSWITCH_PICKUP) - return (cl_weaponswitch & 1) ? ((cl_weaponswitch & 4) ? 2 : 1) : 0; - else if (entry == &ME_SOUND_DUKETALK) - return snd_speech & 1; - else if (entry == &ME_NETOPTIONS_MONSTERS) - return (ud.m_monsters_off ? g_skillCnt : ud.m_player_skill); - - return currentValue; -} - -static void Menu_Verify(int32_t input) -{ - switch (g_currentMenu) - { - case MENU_SAVECLEANVERIFY: - if (input) - { - G_DeleteOldSaves(); - } - break; - - case MENU_RESETPLAYER: - switch (input) - { - default: - inputState.keyFlushChars(); - inputState.ClearKeysDown(); - FX_StopAllSounds(); - - if (G_LoadPlayerMaybeMulti(*g_quickload) == 0) - break; - - // error state, consider as a no instead of yes - g_quickload->reset(); - - fallthrough__; - case 0: - if (sprite[g_player[myconnectindex].ps->i].extra <= 0) - { - if (G_EnterLevel(MODE_GAME)) G_BackToMenu(); - return; - } - - Menu_Change(MENU_CLOSE); - break; - } - break; - - case MENU_LOADVERIFY: - if (input) - { - menusave_t & msv = g_menusaves[M_LOAD.currentEntry]; - savebrief_t & sv = msv.brief; - - if (strcmp(sv.path, g_lastusersave.path) != 0) - { - g_freshload = sv; - g_lastusersave.reset(); - g_lastautosave.reset(); - g_quickload = &g_freshload; - } - else - { - g_quickload = &g_lastusersave; - } - - inputState.keyFlushChars(); - inputState.ClearKeysDown(); - - if (G_LoadPlayerMaybeMulti(sv)) - Menu_Change(MENU_PREVIOUS); - else - Menu_Change(MENU_CLOSE); - } - break; - - case MENU_SAVEVERIFY: - if (!input) - { - save_xxh = 0; - - ((MenuString_t*)M_SAVE.entrylist[M_SAVE.currentEntry]->entry)->editfield = NULL; - } - break; - - case MENU_LOADDELVERIFY: - if (input) - { - G_DeleteSave(g_menusaves[M_LOAD.currentEntry].brief); - Menu_LoadReadHeaders(); - M_LOAD.currentEntry = clamp(M_LOAD.currentEntry, 0, (int32_t)g_nummenusaves-1); - } - break; - case MENU_SAVEDELVERIFY: - if (input) - { - G_DeleteSave(g_menusaves[M_SAVE.currentEntry-1].brief); - Menu_SaveReadHeaders(); - M_SAVE.currentEntry = clamp(M_SAVE.currentEntry, 0, (int32_t)g_nummenusaves); - } - break; - - case MENU_COLCORRRESETVERIFY: - if (input) - { - vid_gamma = 1.f; - vid_contrast = 1.f; - vid_brightness = 0.f; - r_ambientlight = 1.f; - videoSetPalette(0,g_player[myconnectindex].ps->palette,0); - } - break; - - case MENU_KEYSRESETVERIFY: - if (input) - CONFIG_SetDefaultKeys("demolition/defbinds.txt"); - break; - case MENU_KEYSCLASSICVERIFY: - if (input) - CONFIG_SetDefaultKeys("demolition/origbinds.txt"); - break; - case MENU_JOYSTANDARDVERIFY: - if (input) - CONFIG_SetGameControllerDefaultsStandard(); - break; - case MENU_JOYPROVERIFY: - if (input) - CONFIG_SetGameControllerDefaultsPro(); - break; - case MENU_JOYCLEARVERIFY: - if (input) - CONFIG_SetGameControllerDefaultsClear(); - break; - - case MENU_QUIT: - case MENU_QUIT_INGAME: - if (input) - G_GameQuit(); - else - g_quitDeadline = 0; - break; - - case MENU_QUITTOTITLE: - if (input) - { - g_player[myconnectindex].ps->gm = MODE_DEMO; - if (ud.recstat == 1) - G_CloseDemoWrite(); - artClearMapArt(); - } - break; - - case MENU_NETWAITVOTES: - if (!input) - Net_SendMapVoteCancel(0); - break; - - default: - break; - } -} - -static int Menu_CheatStringMatch(char const * input, char const * cheat) -{ - while (*cheat || *input) - { - if (*cheat != *input) - { - if (!(*cheat == '#' && Bisdigit(*input))) - return 0; - } - - ++cheat; - ++input; - } - - return 1; -} - -static void Menu_TextFormSubmit(char *input) -{ - switch (g_currentMenu) - { - case MENU_ADULTPASSWORD: - break; - - case MENU_CHEATENTRY: - { - const size_t inputlength = Bstrlen(input); - Bstrcpy(tempbuf, input); - for (size_t i = 0; i < inputlength; i++) - tempbuf[i] = Btolower(tempbuf[i]); - - int8_t cheatID = -1; - - if (inputlength > 2 && tempbuf[0] == g_keyAsciiTable[CheatKeys[0]] && tempbuf[1] == g_keyAsciiTable[CheatKeys[1]]) - { - for (int i = 0; i < NUMCHEATS; i++) - if (Menu_CheatStringMatch(tempbuf+2, CheatStrings[i])) - { - cheatID = i; - break; - } - } - - switch (cheatID) - { - case -1: - S_PlaySound(KICK_HIT); - break; - case CHEAT_SCOTTY: - { - char const * const numberpos = Bstrchr(CheatStrings[CHEAT_SCOTTY], '#'); - if (numberpos == NULL) - { - S_PlaySound(KICK_HIT); - break; - } - - Menu_Cheat_Warp(input + (numberpos - CheatStrings[CHEAT_SCOTTY]) + 2); - if (g_player[myconnectindex].ps->gm&MODE_MENU) - S_PlaySound(DUKE_GET); - break; - } - case CHEAT_SKILL: - { - char const * const numberpos = Bstrchr(CheatStrings[CHEAT_SKILL], '#'); - if (numberpos == NULL) - { - S_PlaySound(KICK_HIT); - break; - } - - Menu_Cheat_Skill(input + (numberpos - CheatStrings[CHEAT_SKILL]) + 2); - if (g_player[myconnectindex].ps->gm&MODE_MENU) - S_PlaySound(DUKE_GET); - break; - } - default: - Menu_DoCheat(cheatID); - S_PlaySound(DUKE_GET); - break; - } - - if (cheatID >= 0) - cl_cheatmask = cl_cheatmask | CheatFunctionFlags[cheatID]; - - if ((NAM_WW2GI && (cl_cheatmask & (1<fnlist); - - if (object->destination[0] == 0) - { - BDIR * usermaps = Bopendir(object->startdir); - if (usermaps) - { - Bclosedir(usermaps); - Bstrcpy(object->destination, object->startdir); - } - else - Bstrcpy(object->destination, "./"); - } - Bcorrectfilename(object->destination, 1); - - fnlist_getnames(&object->fnlist, object->destination, object->pattern, 0, 0); - object->findhigh[0] = object->fnlist.finddirs; - object->findhigh[1] = object->fnlist.findfiles; - - for (int i = 0; i < 2; ++i) - { - object->scrollPos[i] = 0; - klistbookends(object->findhigh[i]); - } - - object->currentList = 0; - if (object->findhigh[1]) - object->currentList = 1; #endif - inputState.keyFlushChars(); -} - -static void Menu_FileSelect(int32_t input) -{ - switch (g_currentMenu) - { - case MENU_NETUSERMAP: - if ((g_netServer || ud.multimode > 1)) - Net_SendUserMapName(); - fallthrough__; - case MENU_USERMAP: - if (input) - { - ud.m_volume_number = 0; - m_level_number = 7; - - if (g_skillCnt > 0) - Menu_AnimateChange(MENU_SKILL, MA_Advance); - else - Menu_StartGameWithoutSkill(); - } - break; - - default: - break; - } -} - - - - - -static Menu_t* Menu_BinarySearch(MenuID_t query, uint16_t searchstart, uint16_t searchend) -{ - const uint16_t thissearch = (searchstart + searchend) / 2; - const MenuID_t difference = query - Menus[thissearch].menuID; - - if (difference == 0) - return &Menus[thissearch]; - else if (searchstart == searchend) - return NULL; - else if (difference > 0) - { - if (thissearch == searchend) - return NULL; - searchstart = thissearch + 1; - } - else if (difference < 0) - { - if (thissearch == searchstart) - return NULL; - searchend = thissearch - 1; - } - - return Menu_BinarySearch(query, searchstart, searchend); -} - -static Menu_t* Menu_Find(MenuID_t query) -{ - if ((unsigned) query > (unsigned) Menus[numMenus-1].menuID) - return NULL; - - return Menu_BinarySearch(query, 0, numMenus-1); -} - -static Menu_t* Menu_FindFiltered(MenuID_t query) -{ - if ((g_player[myconnectindex].ps->gm&MODE_GAME) && query == MENU_MAIN) - query = MENU_MAIN_INGAME; - - return Menu_Find(query); -} - -MenuAnimation_t m_animation; - -int32_t Menu_Anim_SinOutRight(MenuAnimation_t *animdata) -{ - return sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] - 16384; -} -int32_t Menu_Anim_SinInRight(MenuAnimation_t *animdata) -{ - return sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] + 16384; -} -int32_t Menu_Anim_SinOutLeft(MenuAnimation_t *animdata) -{ - return -sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] + 16384; -} -int32_t Menu_Anim_SinInLeft(MenuAnimation_t *animdata) -{ - return -sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] - 16384; -} - -void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype) -{ - if (cm == MENU_KEYBOARDKEYS) - { - GUICapture |= 2; - return; - } - - if (FURY) - { - m_animation.start = 0; - m_animation.length = 0; - Menu_Change(cm); - return; - } - - switch (animtype) - { - case MA_Advance: - { - Menu_t * const previousMenu = m_currentMenu; - - if (!Menu_Change(cm)) - { - m_animation.out = Menu_Anim_SinOutRight; - m_animation.in = Menu_Anim_SinInRight; - m_animation.start = (int32_t) totalclock; - m_animation.length = 30; - - m_animation.previous = previousMenu; - m_animation.current = m_currentMenu; - } - - break; - } - case MA_Return: - { - Menu_t * const previousMenu = m_currentMenu; - - if (!Menu_Change(cm)) - { - m_animation.out = Menu_Anim_SinOutLeft; - m_animation.in = Menu_Anim_SinInLeft; - m_animation.start = (int32_t) totalclock; - m_animation.length = 30; - - m_animation.previous = previousMenu; - m_animation.current = m_currentMenu; - } - - break; - } - default: - m_animation.start = 0; - m_animation.length = 0; - Menu_Change(cm); - break; - } -} - -static void Menu_MaybeSetSelectionToChild(Menu_t * m, MenuID_t id) -{ - if (m->type == Menu) - { - auto menu = (MenuMenu_t *)m->object; - - if (menu->currentEntry < menu->numEntries) - { - MenuEntry_t const * currentEntry = menu->entrylist[menu->currentEntry]; - if (currentEntry != NULL && currentEntry->type == Link) - { - auto const * link = (MenuLink_t const *)currentEntry->entry; - if (link->linkID == id) - return; // already good to go - } - } - - for (int i = 0, i_end = menu->numEntries; i < i_end; ++i) - { - MenuEntry_t const * entry = menu->entrylist[i]; - if (entry != NULL && entry->type == Link && !(entry->flags & MEF_Hidden)) - { - auto const * link = (MenuLink_t const *)entry->entry; - if (link->linkID == id) - { - menu->currentEntry = i; - Menu_AdjustForCurrentEntryAssignmentBlind(menu); - break; - } - } - } - } -} - -static void Menu_ReadSaveGameHeaders() -{ - ReadSaveGameHeaders(); - - int const numloaditems = max(g_nummenusaves, 1), numsaveitems = g_nummenusaves+1; - ME_LOAD = (MenuEntry_t *)Xrealloc(ME_LOAD, g_nummenusaves * sizeof(MenuEntry_t)); - MEL_LOAD = (MenuEntry_t **)Xrealloc(MEL_LOAD, numloaditems * sizeof(MenuEntry_t *)); - MEO_SAVE = (MenuString_t *)Xrealloc(MEO_SAVE, g_nummenusaves * sizeof(MenuString_t)); - ME_SAVE = (MenuEntry_t *)Xrealloc(ME_SAVE, g_nummenusaves * sizeof(MenuEntry_t)); - MEL_SAVE = (MenuEntry_t **)Xrealloc(MEL_SAVE, numsaveitems * sizeof(MenuEntry_t *)); - - MEL_SAVE[0] = &ME_SAVE_NEW; - ME_SAVE_NEW.name = s_NewSaveGame; - for (int i = 0; i < g_nummenusaves; ++i) - { - MEL_LOAD[i] = &ME_LOAD[i]; - MEL_SAVE[i+1] = &ME_SAVE[i]; - ME_LOAD[i] = ME_LOAD_TEMPLATE; - ME_SAVE[i] = ME_SAVE_TEMPLATE; - ME_SAVE[i].entry = &MEO_SAVE[i]; - MEO_SAVE[i] = MEO_SAVE_TEMPLATE; - - ME_LOAD[i].name = g_menusaves[i].brief.name; - MEO_SAVE[i].variable = g_menusaves[i].brief.name; - } - - if (g_nummenusaves == 0) - MEL_LOAD[0] = &ME_LOAD_EMPTY; - - M_LOAD.entrylist = MEL_LOAD; - M_LOAD.numEntries = numloaditems; - M_SAVE.entrylist = MEL_SAVE; - M_SAVE.numEntries = numsaveitems; - - // lexicographical sorting? -} - -static void Menu_AboutToStartDisplaying(Menu_t * m) -{ - switch (m->menuID) - { - case MENU_MAIN: - if (FURY) - ME_MAIN_LOADGAME.name = s_Continue; - break; - - case MENU_MAIN_INGAME: - if (FURY) - ME_MAIN_LOADGAME.name = s_LoadGame; - break; - - case MENU_NEWGAMECUSTOMSUB: - Menu_PopulateNewGameCustomSub(M_NEWGAMECUSTOM.currentEntry); - break; - - case MENU_LOAD: - if (FURY) - M_LOAD.title = (g_player[myconnectindex].ps->gm & MODE_GAME) ? s_LoadGame : s_Continue; - - Menu_LoadReadHeaders(); - - if (g_quickload && g_quickload->isValid()) - { - for (int i = 0; i < g_nummenusaves; ++i) - { - if (strcmp(g_menusaves[i].brief.path, g_quickload->path) == 0) - { - M_LOAD.currentEntry = i; - Menu_AdjustForCurrentEntryAssignmentBlind(&M_LOAD); - break; - } - } - } - break; - - case MENU_SAVE: - if (g_previousMenu == MENU_SAVEVERIFY || g_previousMenu == MENU_SAVEDELVERIFY) - break; - - Menu_SaveReadHeaders(); - - if (g_lastusersave.isValid()) - { - for (int i = 0; i < g_nummenusaves; ++i) - { - if (strcmp(g_menusaves[i].brief.path, g_lastusersave.path) == 0) - { - M_SAVE.currentEntry = i+1; - Menu_AdjustForCurrentEntryAssignmentBlind(&M_SAVE); - break; - } - } - } - - if (g_player[myconnectindex].ps->gm&MODE_GAME) - { - g_screenCapture = 1; - G_DrawRooms(myconnectindex,65536); - g_screenCapture = 0; - } - break; - - case MENU_VIDEOSETUP: - newresolution = 0; - for (int i = 0; i < MAXVALIDMODES; ++i) - { - if (resolution[i].xdim == xres && resolution[i].ydim == yres) - { - newresolution = i; - break; - } - } - newrendermode = videoGetRenderMode(); - newfullscreen = fullscreen; - newvsync = vid_vsync; - newborderless = r_borderless; - break; - - case MENU_ADVSOUND: - soundrate = snd_mixrate; - soundvoices = snd_numvoices; - musicdevice = MusicDevice; - break; - - default: - break; - } - - switch (m->type) - { - case TextForm: - typebuf[0] = 0; - ((MenuTextForm_t*)m->object)->input = typebuf; - break; - case FileSelect: - Menu_FileSelectInit((MenuFileSelect_t*)m->object); - break; - case Menu: - { - auto menu = (MenuMenu_t*)m->object; - // MenuEntry_t* currentry = menu->entrylist[menu->currentEntry]; - - // need this for MENU_SKILL - if (menu->currentEntry >= menu->numEntries) - menu->currentEntry = 0; - - int32_t i = menu->currentEntry; - while (!menu->entrylist[menu->currentEntry] || - (((MenuEntry_t*)menu->entrylist[menu->currentEntry])->flags & MEF_Hidden) || - ((MenuEntry_t*)menu->entrylist[menu->currentEntry])->type == Spacer) - { - menu->currentEntry++; - if (menu->currentEntry >= menu->numEntries) - menu->currentEntry = 0; - if (menu->currentEntry == i) - G_GameExit("Menu_Change: Attempted to show a menu with no entries."); - } - - Menu_EntryFocus(/*currentry*/); - break; - } - default: - break; - } -} - -static void Menu_ChangingTo(Menu_t * m) -{ -#ifdef __ANDROID__ - if (m->menuID == MENU_TOUCHBUTTONS) - AndroidToggleButtonEditor(); -#endif - - switch (m->type) - { - case TextForm: - Menu_StartTextInput(); - break; - default: - break; - } -} - -int Menu_Change(MenuID_t cm) -{ - Menu_t * beginMenu = m_currentMenu; - - cm = VM_OnEventWithReturn(EVENT_CHANGEMENU, g_player[screenpeek].ps->i, screenpeek, cm); - - if (cm == MENU_PREVIOUS) - { - m_currentMenu = m_previousMenu; - g_currentMenu = g_previousMenu; - } - else if (cm == MENU_CLOSE) - Menu_Close(myconnectindex); - else if (cm >= 0) - { - Menu_t * search = Menu_FindFiltered(cm); - - if (search == NULL) - return 0; // intentional, so that users don't use any random value as "don't change" - - // security - if (search->type == Verify && - search->parentID != MENU_PREVIOUS && - search->parentID != MENU_CLOSE && - search->parentID != g_currentMenu) - return 1; - - m_previousMenu = m_currentMenu; - g_previousMenu = g_currentMenu; - m_currentMenu = search; - g_currentMenu = search->menuID; - } - else - return 1; - - if (FURY) - { - Menu_t * parent = m_currentMenu, * result = NULL; - - while (parent != NULL && parent->menuID != MENU_OPTIONS && parent->menuID != MENU_MAIN && parent->menuID != MENU_MAIN_INGAME) - { - result = parent = Menu_FindFiltered(parent->parentID); - } - - m_parentMenu = result; - - if (result) - { - Menu_MaybeSetSelectionToChild(result, m_currentMenu->menuID); - Menu_AboutToStartDisplaying(result); - } - } - - Menu_MaybeSetSelectionToChild(m_currentMenu, beginMenu->menuID); - Menu_AboutToStartDisplaying(m_currentMenu); - Menu_ChangingTo(m_currentMenu); - -#if !defined EDUKE32_TOUCH_DEVICES - m_menuchange_watchpoint = 1; -#endif - - return 0; -} - - - - - - - - - - -int G_CheckPlayerColor(int color) -{ - for (int i : MEOSV_PLAYER_COLOR) - if (i == color) - return color; - - return -1; -} - - -int32_t Menu_DetermineSpecialState(MenuEntry_t *entry) -{ - if (entry == NULL) - return 0; - - if (entry->type == String) - { - if (((MenuString_t*)entry->entry)->editfield) - return 1; - } - else if (entry->type == Option) - { - if (((MenuOption_t*)entry->entry)->options->currentEntry >= 0) - return 2; - } - else if (entry->type == Custom2Col) - { - if (((MenuCustom2Col_t*)entry->entry)->screenOpen) - return 2; - } - - return 0; -} - -int32_t Menu_IsTextInput(Menu_t *cm) -{ - switch (m_currentMenu->type) - { - case Verify: - case TextForm: - case FileSelect: - case Message: - return 1; - break; - case Panel: - return 0; - break; - case Menu: - { - auto menu = (MenuMenu_t *)cm->object; - auto entry = menu->entrylist[menu->currentEntry]; - return Menu_DetermineSpecialState(entry); - } - break; - } - - return 0; -} - -static inline int32_t Menu_BlackTranslucentBackgroundOK(MenuID_t cm) -{ - switch (cm) - { - case MENU_COLCORR: - case MENU_COLCORR_INGAME: - return 0; - break; - default: - return 1; - break; - } - - return 1; -} - -static inline int32_t Menu_UpdateScreenOK(MenuID_t cm) -{ - switch (cm) - { - case MENU_LOAD: - case MENU_SAVE: - case MENU_LOADVERIFY: - case MENU_LOADDELVERIFY: - case MENU_SAVEVERIFY: - case MENU_SAVEDELVERIFY: - return 0; - break; - default: - return 1; - break; - } - - return 1; -} - - -/* - Code below this point is entirely general, - so if you want to change or add a menu, - chances are you should scroll up. -*/ - -int32_t m_mouselastactivity; -#if !defined EDUKE32_TOUCH_DEVICES -int32_t m_mousewake_watchpoint, m_menuchange_watchpoint; -#endif -int32_t m_mousecaught; -static vec2_t m_prevmousepos, m_mousepos, m_mousedownpos; - -void Menu_Open(uint8_t playerID) -{ - g_player[playerID].ps->gm |= MODE_MENU; - - inputState.mouseReadAbs(&m_prevmousepos); - m_mouselastactivity = -M_MOUSETIMEOUT; - -#if !defined EDUKE32_TOUCH_DEVICES - m_mousewake_watchpoint = 0; -#endif - - mouseLockToWindow(0); -} - -void Menu_Close(uint8_t playerID) -{ - auto & gm = g_player[playerID].ps->gm; - if (gm & MODE_GAME) - { - if (gm & MODE_MENU) - I_ClearAllInput(); - - // The following lines are here so that you cannot close the menu when no game is running. - gm &= ~MODE_MENU; - mouseLockToWindow(1); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 1; - totalclock = ototalclock; - CAMERACLOCK = (int32_t) totalclock; - CAMERADIST = 65536; - m_animation.start = 0; - m_animation.length = 0; - - // Reset next-viewscreen-redraw counter. - // XXX: are there any other cases like that in need of handling? - if (g_curViewscreen >= 0) - actor[g_curViewscreen].t_data[0] = (int32_t) totalclock; - } - - G_UpdateScreenArea(); - S_PauseSounds(false); - } -} - -static int32_t x_widescreen_left(void) -{ - return (320<<15) - scale(240<<15, xdim, ydim); -} - -static int32_t xdim_from_320_16(int32_t x) -{ - const int32_t screenwidth = scale(240<<16, xdim, ydim); - return scale(x + (screenwidth>>1) - (160<<16), xdim, screenwidth); -} -static int32_t ydim_from_200_16(int32_t y) -{ - y = mulscale16(y + rotatesprite_y_offset - (200<<15), rotatesprite_yxaspect) + (200<<15); - return scale(y, ydim, 200<<16); -} - -static void Menu_BlackRectangle(int32_t x, int32_t y, int32_t width, int32_t height, int32_t orientation) -{ - const int32_t xscale = divscale16(width, tilesiz[0].x<<16), yscale = divscale16(height, tilesiz[0].y<<16); - - rotatesprite_(x, y, max(xscale, yscale), 0, 0, 127, ud.shadow_pal, (orientation&(1|32))|2|8|16, 0, 0, xdim_from_320_16(x), ydim_from_200_16(y), xdim_from_320_16(x + width), ydim_from_200_16(y + height)); -} - -enum MenuTextFlags_t -{ - MT_Selected = 1<<0, - MT_Disabled = 1<<1, - MT_XCenter = 1<<2, - MT_XRight = 1<<3, - MT_YCenter = 1<<4, - MT_Literal = 1<<5, - MT_RightSide = 1<<6, -}; - -static void Menu_GetFmt(const MenuFont_t *font, uint8_t const status, int32_t *s, int32_t *z) -{ - if (status & MT_Selected) - *s = VM_OnEventWithReturn(EVENT_MENUSHADESELECTED, -1, myconnectindex, sintable[((int32_t) totalclock<<5)&2047]>>12); - else - *s = font->shade_deselected; - // sum shade values - if (status & MT_Disabled) - *s += font->shade_disabled; - - if (FURY && status & MT_Selected) - *z += (*z >> 4); -} - -static vec2_t Menu_Text(int32_t x, int32_t y, const MenuFont_t *font, const char *t, uint8_t status, int32_t ydim_upper, int32_t ydim_lower) -{ - int32_t s, p, ybetween = font->between.y; - int32_t f = font->textflags; - if (status & MT_XCenter) - f |= TEXT_XCENTER; - if (status & MT_XRight) - f |= TEXT_XRIGHT; - if (status & MT_YCenter) - { - f |= TEXT_YCENTER | TEXT_YOFFSETZERO; - ybetween = font->emptychar.y; // <^ the battle against 'Q' - } - if (status & MT_Literal) - f |= TEXT_LITERALESCAPE; - - int32_t z = font->zoom; - - if (status & MT_Disabled) - p = (status & MT_RightSide) ? font->pal_disabled_right : font->pal_disabled; - else if (status & MT_Selected) - p = (status & MT_RightSide) ? font->pal_selected_right : font->pal_selected; - else - p = (status & MT_RightSide) ? font->pal_deselected_right : font->pal_deselected; - - Menu_GetFmt(font, status, &s, &z); - - return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2|8|16|ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim-1, ydim_lower); -} - -#if 0 -static vec2_t Menu_TextSize(int32_t x, int32_t y, const MenuFont_t *font, const char *t, uint8_t status) -{ - int32_t f = font->textflags; - if (status & MT_Literal) - f |= TEXT_LITERALESCAPE; - - return G_ScreenTextSize(font->tilenum, x, y, font->zoom, 0, t, 2|8|16|ROTATESPRITE_FULL16, font->emptychar.x, font->emptychar.y, font->between.x, font->between.y, f, 0, 0, xdim-1, ydim-1); -} -#endif - -static int32_t Menu_FindOptionBinarySearch(MenuOption_t *object, const int32_t query, uint16_t searchstart, uint16_t searchend) -{ - const uint16_t thissearch = (searchstart + searchend) / 2; - const bool isIdentityMap = object->options->optionValues == NULL; - const int32_t destination = isIdentityMap ? (int32_t)thissearch : object->options->optionValues[thissearch]; - const int32_t difference = query - destination; - - Bassert(!isIdentityMap || query >= 0); - - if (difference == 0) - return thissearch; - else if (searchstart == searchend) - return -1; - else if (difference > 0) - { - if (thissearch == searchend) - return -1; - searchstart = thissearch + 1; - } - else if (difference < 0) - { - if (thissearch == searchstart) - return -1; - searchend = thissearch - 1; - } - - return Menu_FindOptionBinarySearch(object, query, searchstart, searchend); -} - -static int32_t Menu_MouseOutsideBounds(vec2_t const * const pos, const int32_t x, const int32_t y, const int32_t width, const int32_t height) -{ - return pos->x < x || pos->x >= x + width || pos->y < y || pos->y >= y + height; -} - -static void Menu_RunScrollbar(Menu_t *cm, MenuMenuFormat_t const * const format, const int32_t totalextent, int32_t * const scrollPos, const int32_t rightedge, const vec2_t origin) -{ - if (totalextent > klabs(format->bottomcutoff)) - { - int32_t scrollTile = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum : -1; - int32_t scrollTileTop = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 1 : -1; - int32_t scrollTileBottom = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 2 : -1; - int32_t scrollTileCursor = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 3 : SELECTDIR; - - const int32_t scrollwidth = (scrollTile >= 0) ? tilesiz[scrollTile].x*ud.menu_scrollbarz : tilesiz[scrollTileCursor].x*ud.menu_scrollcursorz; - const int32_t scrollx = origin.x + rightedge - scrollwidth, scrolly = origin.y + format->pos.y; - const int32_t scrollheight = klabs(format->bottomcutoff) - format->pos.y; - int32_t scrollregionstart = scrolly; - int32_t scrollregionend = scrolly + scrollheight; - if (ud.menu_scrollbartilenum >= 0) - { - scrollregionstart += tilesiz[scrollTileTop].y*ud.menu_scrollbarz; - scrollregionend -= tilesiz[scrollTileBottom].y*ud.menu_scrollbarz; - } - const int32_t scrollregionheight = scrollregionend - scrollregionstart - (tilesiz[scrollTileCursor].y*ud.menu_scrollcursorz); - const int32_t scrollPosMax = totalextent - klabs(format->bottomcutoff); - - if (scrollTile >= 0) - { - // draw the scrollbar (minus the top tile) twice to fill the gaps between tiles - if (tilesiz[scrollTile].y > 0) - { - for (int32_t y = scrollregionstart + ((tilesiz[scrollTileTop].y == 0)*tilesiz[scrollTile].y*ud.menu_scrollbarz); y < scrollregionend; y += tilesiz[scrollTile].y*ud.menu_scrollbarz) - rotatesprite(scrollx, y - (ud.menu_scrollbarz>>1), ud.menu_scrollbarz, 0, scrollTile, 0, 0, 26, 0, 0, xdim-1, mulscale16(scrollregionend, ydim*200)-1); - } - rotatesprite_fs(scrollx, scrollregionend - (ud.menu_scrollbarz>>1), ud.menu_scrollbarz, 0, scrollTileBottom, 0, 0, 26); - - if (tilesiz[scrollTile].y > 0) - { - for (int32_t y = scrollregionstart; y < scrollregionend; y += tilesiz[scrollTile].y*ud.menu_scrollbarz) - rotatesprite(scrollx, y, ud.menu_scrollbarz, 0, scrollTile, 0, 0, 26, 0, 0, xdim-1, mulscale16(scrollregionend, ydim*200)-1); - } - rotatesprite_fs(scrollx, scrolly, ud.menu_scrollbarz, 0, scrollTileTop, 0, 0, 26); - rotatesprite_fs(scrollx, scrollregionend, ud.menu_scrollbarz, 0, scrollTileBottom, 0, 0, 26); - } - else - Menu_BlackRectangle(scrollx, scrolly, scrollwidth, scrollheight, 1|32); - - rotatesprite_fs(scrollx + ((scrollwidth>>17)<<16) - ((tilesiz[scrollTileCursor].x>>1)*ud.menu_scrollcursorz), scrollregionstart + scale(scrollregionheight, *scrollPos, scrollPosMax), ud.menu_scrollcursorz, 0, scrollTileCursor, 0, 0, 26); - - if (cm == m_currentMenu && !m_mousecaught && MOUSEACTIVECONDITIONAL(inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - const int32_t scrolltilehalfheight = (tilesiz[scrollTileCursor].y>>1)*ud.menu_scrollcursorz; - const int32_t scrollregiony = scrollregionstart + scrolltilehalfheight; - - // region between the y-midline of the arrow at the extremes scrolls proportionally - if (!Menu_MouseOutsideBounds(&m_mousepos, scrollx, scrollregiony, scrollwidth, scrollregionheight)) - { - *scrollPos = scale(m_mousepos.y - scrollregiony, scrollPosMax, scrollregionheight); - - m_mousecaught = 1; - } - // region outside the y-midlines clamps to the extremes - else if (!Menu_MouseOutsideBounds(&m_mousepos, scrollx, scrolly, scrollwidth, scrollheight)) - { - if (m_mousepos.y > scrolly + ((scrollheight>>17)<<16)) - *scrollPos = scrollPosMax; - else - *scrollPos = 0; - - m_mousecaught = 1; - } - } - } -} - -typedef enum MenuMovement_t -{ - MM_Up = 1, - MM_End = 3, - MM_Down = 4, - MM_Home = 12, - MM_Left = 16, - MM_AllTheWayLeft = 48, - MM_Right = 64, - MM_AllTheWayRight = 192, - MM_Swap = 80, -} MenuMovement_t; - -static MenuEntry_t *Menu_RunInput_Menu_MovementVerify(MenuMenu_t *menu); -static MenuEntry_t *Menu_RunInput_Menu_Movement(MenuMenu_t *menu, MenuMovement_t direction); -static void Menu_RunInput_EntryLink_Activate(MenuEntry_t *entry); -static void Menu_RunInput_EntryOptionList_MovementVerify(MenuOption_t *object); -static void Menu_RunInput_EntryOptionList_Movement(MenuOption_t *object, MenuMovement_t direction); -static int32_t Menu_RunInput_EntryOption_Modify(MenuEntry_t *entry, MenuOption_t *object, int32_t newValueIndex); -static int32_t Menu_RunInput_EntryOption_Movement(MenuEntry_t *entry, MenuOption_t *object, MenuMovement_t direction); -static int32_t Menu_RunInput_EntryOption_Activate(MenuEntry_t *entry, MenuOption_t *object); -static int32_t Menu_RunInput_EntryOptionList_Activate(MenuEntry_t *entry, MenuOption_t *object); -static void Menu_RunInput_EntryCustom2Col_Activate(MenuEntry_t *entry); -static void Menu_RunInput_EntryRangeInt32_MovementVerify(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue); -static void Menu_RunInput_EntryRangeInt32_MovementArbitrary(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue); -static void Menu_RunInput_EntryRangeInt32_Movement(MenuEntry_t *entry, MenuRangeInt32_t *object, MenuMovement_t direction); -static void Menu_RunInput_EntryRangeFloat_MovementVerify(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue); -static void Menu_RunInput_EntryRangeFloat_MovementArbitrary(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue); -static void Menu_RunInput_EntryRangeFloat_Movement(MenuEntry_t *entry, MenuRangeFloat_t *object, MenuMovement_t direction); -#ifdef MENU_ENABLE_RANGEDOUBLE -static void Menu_RunInput_EntryRangeDouble_MovementVerify(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue); -static void Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue); -static void Menu_RunInput_EntryRangeDouble_Movement(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, MenuMovement_t direction); -#endif -static void Menu_RunInput_EntryString_Activate(MenuEntry_t *entry); -static void Menu_RunInput_EntryString_Submit(/*MenuEntry_t *entry, */MenuString_t *object); -static void Menu_RunInput_EntryString_Cancel(/*MenuEntry_t *entry, */MenuString_t *object); -static void Menu_RunInput_FileSelect_MovementVerify(MenuFileSelect_t *object); -static void Menu_RunInput_FileSelect_Movement(MenuFileSelect_t *object, MenuMovement_t direction); -static void Menu_RunInput_FileSelect_Select(MenuFileSelect_t *object); - -static int32_t M_RunMenu_Menu(Menu_t *cm, MenuMenu_t *menu, MenuEntry_t *currentry, int32_t state, const vec2_t origin, bool actually_draw) -{ - int32_t totalHeight = 0; - - // RIP MenuGroup_t b. 2014-03-?? d. 2014-11-29 - { - int32_t e; - const int32_t y_upper = menu->format->pos.y; - const int32_t y_lower = klabs(menu->format->bottomcutoff); - int32_t y = 0; - int32_t calculatedentryspacing = 0; - - if (menu->format->bottomcutoff < 0) - { - int32_t totalheight = 0, numvalidentries = 0; - - for (e = 0; e < menu->numEntries; ++e) - { - MenuEntry_t *entry = menu->entrylist[e]; - - if (entry == NULL || (entry->flags & MEF_Hidden)) - continue; - - ++numvalidentries; - - // assumes height == font->get_yline()! - totalheight += entry->getHeight(); - } - - calculatedentryspacing = (klabs(menu->format->bottomcutoff) - menu->format->pos.y - totalheight) / (numvalidentries > 1 ? numvalidentries - 1 : 1); - } - - // totalHeight calculating pass - for (e = 0; e < menu->numEntries; ++e) - { - MenuEntry_t *entry = menu->entrylist[e]; - - if (entry == NULL || (entry->flags & MEF_Hidden)) - continue; - - int32_t const height = entry->getHeight(); - - y += height; - totalHeight = y; - y += (!calculatedentryspacing || calculatedentryspacing > entry->getMarginBottom()) ? entry->getMarginBottom() : calculatedentryspacing; - } - y = 0; - - int32_t ydim_upper, ydim_lower; - if (y_upper + totalHeight > y_lower) - { - ydim_upper = ydim_from_200_16(origin.y + y_upper); - ydim_lower = ydim_from_200_16(origin.y + y_lower); - } - else - { - ydim_upper = 0; - ydim_lower = ydim-1; - } - - for (e = 0; e < menu->numEntries; ++e) - { - MenuEntry_t *entry = menu->entrylist[e]; - - if (entry == NULL || (entry->flags & MEF_Hidden)) - continue; - - int32_t const indent = entry->getIndent(); - int32_t x = menu->format->pos.x; - - uint8_t status = 0; - if (e == menu->currentEntry) - status |= MT_Selected; - if (entry->flags & (MEF_Disabled|MEF_LookDisabled)) - status |= MT_Disabled; - if (entry->format->width == 0) - status |= MT_XCenter; - - bool const dodraw = entry->type != Spacer && actually_draw && - 0 <= y - menu->scrollPos + entry->font->get_yline() && - y - menu->scrollPos <= klabs(menu->format->bottomcutoff) - menu->format->pos.y; - - int32_t const height = entry->getHeight(); // max(textsize.y, entry->font->get_yline()); // bluefont Q ruins this - status |= MT_YCenter; - int32_t const y_internal = origin.y + y_upper + y + ((height>>17)<<16) - menu->scrollPos; - - vec2_t textsize; - if (dodraw) - textsize = Menu_Text(origin.x + x + indent, y_internal, entry->font, entry->name, status, ydim_upper, ydim_lower); - - if (entry->format->width < 0) - status |= MT_XRight; - - if (dodraw && (status & MT_Selected) && state != 1) - { - if (status & MT_XCenter) - { - Menu_DrawCursorLeft(origin.x + (MENU_MARGIN_CENTER<<16) + entry->font->cursorCenterPosition, y_internal, entry->font->cursorScale); - Menu_DrawCursorRight(origin.x + (MENU_MARGIN_CENTER<<16) - entry->font->cursorCenterPosition, y_internal, entry->font->cursorScale); - } - else - Menu_DrawCursorLeft(origin.x + x + indent - entry->font->cursorLeftPosition, y_internal, entry->font->cursorScale); - } - - if (entry->name != nullptr && entry->name[0] != '\0') - status |= MT_RightSide; - - // need this up here to avoid race conditions - entry->ybottom = (entry->ytop = y_upper + y) + height; - - if (dodraw) - { - const int32_t mousex = origin.x + indent + entry->format->width == 0 ? x - ((textsize.x>>17)<<16) : x; - const int32_t mousey = origin.y + y_upper + y - menu->scrollPos; - int32_t mousewidth = entry->format->width == 0 ? textsize.x : klabs(entry->format->width); - - if (entry->name) - x += klabs(entry->format->width); - - switch (entry->type) - { - case Spacer: - break; - case Dummy: - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - } - break; - case Link: - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, entry->font->get_yline())) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryLink_Activate(entry); - - if (g_player[myconnectindex].ps->gm&MODE_MENU) // for skill selection - S_PlaySound(PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - break; - case Option: - { - auto object = (MenuOption_t*)entry->entry; - int32_t currentOption = Menu_FindOptionBinarySearch(object, object->cVar == NULL ? Menu_EntryOptionSource(entry, object->currentOption) : object->cVar->ToInt(), 0, object->options->numOptions); - - if (currentOption >= 0) - object->currentOption = currentOption; - - int32_t optiontextx = origin.x + x; - const int32_t optiontexty = origin.y + y_upper + y - menu->scrollPos; - - const vec2_t optiontextsize = Menu_Text(optiontextx, optiontexty + ((height>>17)<<16), object->font, - currentOption < 0 ? MenuCustom : currentOption < object->options->numOptions ? object->options->optionNames[currentOption] : NULL, - status, ydim_upper, ydim_lower); - - if (entry->format->width > 0) - mousewidth += optiontextsize.x; - else - optiontextx -= optiontextsize.x; - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, entry->font->get_yline())) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryOption_Activate(entry, object); - - S_PlaySound(PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - - break; - } - case Custom2Col: - { - auto object = (MenuCustom2Col_t*)entry->entry; - int32_t columnx[2] = { origin.x + x - ((status & MT_XRight) ? object->columnWidth : 0), origin.x + x + ((status & MT_XRight) ? 0 : object->columnWidth) }; - const int32_t columny = origin.y + y_upper + y - menu->scrollPos; - - // Beware of hack job! - auto keys = Bindings.GetKeysForCommand(buttonMap.GetButtonName(object->buttonindex)); - FString text1; - FString text2; - if (keys.Size() > 0) text1 = C_NameKeys(&keys[0], 1); - if (keys.Size() > 1) text2 = C_NameKeys(&keys[1], 1); - const vec2_t column0textsize = Menu_Text(columnx[0], columny + ((height >> 17) << 16), object->font, text1, menu->currentColumn == 0 ? status : (status & ~MT_Selected), ydim_upper, ydim_lower); - const vec2_t column1textsize = Menu_Text(columnx[1], columny + ((height>>17)<<16), object->font, text2, menu->currentColumn == 1 ? status : (status & ~MT_Selected), ydim_upper, ydim_lower); - - if (entry->format->width > 0) - mousewidth += object->columnWidth + column1textsize.x; - else - { - columnx[0] -= column0textsize.x; - columnx[1] -= column0textsize.x; - } - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!Menu_MouseOutsideBounds(&m_mousepos, columnx[1], mousey, column1textsize.x, object->font->get_yline())) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, columnx[1], mousey, column1textsize.x, object->font->get_yline()))) - { - menu->currentColumn = 1; - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, columnx[1], mousey, column1textsize.x, object->font->get_yline())) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - menu->currentColumn = 1; - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryCustom2Col_Activate(entry); - - S_PlaySound(PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - else if (!Menu_MouseOutsideBounds(&m_mousepos, columnx[0], mousey, column0textsize.x, object->font->get_yline())) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, columnx[0], mousey, column0textsize.x, object->font->get_yline()))) - { - menu->currentColumn = 0; - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, columnx[0], mousey, column0textsize.x, object->font->get_yline())) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - menu->currentColumn = 0; - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryCustom2Col_Activate(entry); - - S_PlaySound(PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - } - break; - } - case RangeInt32: - { - auto object = (MenuRangeInt32_t*)entry->entry; - - int32_t s, p; - int32_t z = entry->font->cursorScale; - Menu_GetFmt(object->font, status|MT_RightSide, &s, &z); - - if (status & MT_Disabled) - p = ud.slidebar_paldisabled; - else if (status & MT_Selected) - p = ud.slidebar_palselected; - else - p = 0; - - const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z); - const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z); - - if (status & MT_XRight) - x -= slidebarwidth; - else - mousewidth += slidebarwidth; - - const int32_t slidebarx = origin.x + x; - const int32_t slidebary = origin.y + y_upper + y + (((height - slidebarheight)>>17)<<16) - menu->scrollPos; - - rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[SLIDEBAR+1].x * ud.menu_slidecursorz), z); - const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + scale(slideregionwidth, *object->cVar - object->min, object->max - object->min); - const int32_t slidepointy = slidebary + mulscale16((((tilesiz[SLIDEBAR].y>>1) * ud.menu_slidebarz) - ((tilesiz[SLIDEBAR+1].y>>1) * ud.menu_slidecursorz)), z); - - rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, SLIDEBAR+1, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - if (object->flags & DisplayTypeMask) - { - status |= MT_XRight; - - int32_t onehundredpercent = object->onehundredpercent; - if (onehundredpercent == 0) - onehundredpercent = object->max; - - switch (object->flags & DisplayTypeMask) - { - case DisplayTypeInteger: - Bsprintf(tempbuf, "%d", **object->cVar); - break; - case DisplayTypePercent: - Bsprintf(tempbuf, "%d%%", roundscale(*object->cVar, 100, onehundredpercent)); - break; - case DisplayTypeNormalizedDecimal: - Bsprintf(tempbuf, "%.2f", (double) *object->cVar / (double) onehundredpercent); - break; - } - - Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + ((height>>17)<<16) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower); - } - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - const int32_t slidepointhalfwidth = mulscale16((((tilesiz[SLIDEBAR+1].x)*ud.menu_slidecursorz)>>2) + ud.menu_slidebarmargin, z); - const int32_t slideregionx = slidebarx + slidepointhalfwidth; - - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - // region between the x-midline of the slidepoint at the extremes slides proportionally - if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height)) - { - Menu_RunInput_EntryRangeInt32_MovementArbitrary(entry, object, roundscale(object->max - object->min, m_mousepos.x - slideregionx, slideregionwidth) + object->min); - - m_mousecaught = 1; - } - // region outside the x-midlines clamps to the extremes - else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height)) - { - if (m_mousepos.x > slideregionx + ((slideregionwidth>>17)<<16)) - Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, object->max); - else - Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, object->min); - - m_mousecaught = 1; - } - } - } - - break; - } - case RangeFloat: - { - auto object = (MenuRangeFloat_t*)entry->entry; - - int32_t s, p; - int32_t z = entry->font->cursorScale; - Menu_GetFmt(object->font, status|MT_RightSide, &s, &z); - - if (status & MT_Disabled) - p = ud.slidebar_paldisabled; - else if (status & MT_Selected) - p = ud.slidebar_palselected; - else - p = 0; - - const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z); - const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z); - - if (status & MT_XRight) - x -= slidebarwidth; - else - mousewidth += slidebarwidth; - - const int32_t slidebarx = origin.x + x; - const int32_t slidebary = origin.y + y_upper + y + (((height - slidebarheight)>>17)<<16) - menu->scrollPos; - - rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[SLIDEBAR+1].x * ud.menu_slidecursorz), z); - const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + Blrintf((float) slideregionwidth * (*object->cVar - object->min) / (object->max - object->min)); - const int32_t slidepointy = slidebary + mulscale16(((tilesiz[SLIDEBAR].y>>1) * ud.menu_slidebarz) - ((tilesiz[SLIDEBAR+1].y>>1) * ud.menu_slidecursorz), z); - - rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, SLIDEBAR+1, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - if (object->flags & DisplayTypeMask) - { - status |= MT_XRight; - - float onehundredpercent = object->onehundredpercent; - if (onehundredpercent == 0.f) - onehundredpercent = 1.f; - - switch (object->flags & DisplayTypeMask) - { - case DisplayTypeInteger: - Bsprintf(tempbuf, "%.2f", **object->cVar); - break; - case DisplayTypePercent: - Bsprintf(tempbuf, "%ld%%", lrintf(*object->cVar * 100.f / onehundredpercent)); - break; - case DisplayTypeNormalizedDecimal: - Bsprintf(tempbuf, "%.2f", *object->cVar / onehundredpercent); - break; - } - - Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + ((height>>17)<<16) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower); - } - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - const int32_t slidepointhalfwidth = mulscale16((2+tilesiz[SLIDEBAR+1].x)<<15, z); - const int32_t slideregionx = slidebarx + slidepointhalfwidth; - - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - // region between the x-midline of the slidepoint at the extremes slides proportionally - if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height)) - { - Menu_RunInput_EntryRangeFloat_MovementArbitrary(entry, object, (object->max - object->min) * (m_mousepos.x - slideregionx) / slideregionwidth + object->min); - - m_mousecaught = 1; - } - // region outside the x-midlines clamps to the extremes - else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height)) - { - if (m_mousepos.x > slideregionx + (slideregionwidth>>17<<16)) - Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, object->max); - else - Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, object->min); - - m_mousecaught = 1; - } - } - } - - break; - } -#ifdef MENU_ENABLE_RANGEDOUBLE - case RangeDouble: - { - MenuRangeDouble_t *object = (MenuRangeDouble_t*)entry->entry; - - int32_t s, p; - int32_t z = entry->font->cursorScale; - Menu_GetFmt(object->font, status|MT_RightSide, &s, &z); - - if (status & MT_Disabled) - p = ud.slidebar_paldisabled; - else if (status & MT_Selected) - p = ud.slidebar_palselected; - else - p = 0; - - const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z); - const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z); - - if (status & MT_XRight) - x -= slidebarwidth; - else - mousewidth += slidebarwidth; - - const int32_t slidebarx = origin.x + x; - const int32_t slidebary = origin.y + y_upper + y + (((height - slidebarheight)>>17)<<16) - menu->scrollPos; - - rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[SLIDEBAR+1].x * ud.menu_slidecursorz), z); - const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + lrint((double) slideregionwidth * (*object->variable - object->min) / (object->max - object->min)); - const int32_t slidepointy = slidebary + mulscale16(((tilesiz[SLIDEBAR].y)>>1 * ud.menu_slidebarz) - ((tilesiz[SLIDEBAR+1].y)>>1 * ud.menu_slidecursorz), z); - - rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, SLIDEBAR+1, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - if (object->flags & DisplayTypeMask) - { - status |= MT_XRight; - - double onehundredpercent = object->onehundredpercent; - if (onehundredpercent == 0.) - onehundredpercent = 1.; - - switch (object->flags & DisplayTypeMask) - { - case DisplayTypeInteger: - Bsprintf(tempbuf, "%.2f", *object->variable); - break; - case DisplayTypePercent: - Bsprintf(tempbuf, "%ld%%", lrint(*object->variable * 100. / onehundredpercent)); - break; - case DisplayTypeNormalizedDecimal: - Bsprintf(tempbuf, "%.2f", *object->variable / onehundredpercent); - break; - } - - Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + ((height>>17)<<16) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower); - } - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - const int32_t slidepointhalfwidth = mulscale16((2+tilesiz[SLIDEBAR+1].x)<<15, z); - const int32_t slideregionx = slidebarx + slidepointhalfwidth; - - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - // region between the x-midline of the slidepoint at the extremes slides proportionally - if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height)) - { - Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*entry, */object, (object->max - object->min) * (m_mousepos.x - slideregionx) / slideregionwidth + object->min); - - m_mousecaught = 1; - } - // region outside the x-midlines clamps to the extremes - else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height)) - { - if (m_mousepos.x > slideregionx + ((slideregionwidth>>17)<<16)) - Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, object->max); - else - Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, object->min); - - m_mousecaught = 1; - } - } - } - - break; - } -#endif - case String: - { - auto object = (MenuString_t*)entry->entry; - - vec2_t dim; - int32_t stringx = x; - const int32_t stringy = origin.y + y_upper + y + ((height>>17)<<16) - menu->scrollPos; - int32_t h; - - if (entry == currentry && object->editfield != NULL) - { - dim = Menu_Text(origin.x + stringx, stringy, object->font, object->editfield, (status & ~MT_Disabled) | MT_Literal, ydim_upper, ydim_lower); - h = max(dim.y, entry->font->get_yline()); - - Menu_DrawCursorText(origin.x + x + dim.x + (1<<16), stringy, h, ydim_upper, ydim_lower); - } - else - { - dim = Menu_Text(origin.x + stringx, stringy, object->font, object->variable, status, ydim_upper, ydim_lower); - h = max(dim.y, entry->font->get_yline()); - } - - if (entry->format->width > 0) - { - if (entry->name) - mousewidth += dim.x; - } - else - stringx -= dim.x; - - if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, h))) - { - if (state != 1 && Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, h)) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - #ifndef EDUKE32_TOUCH_DEVICES - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, h) && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, h)) - #endif - { - if (entry == currentry && object->editfield != NULL) - { - Menu_RunInput_EntryString_Submit(/*entry, */object); - - S_PlaySound(PISTOL_BODYHIT); - - m_mousecaught = 1; - } - else if (state != 1) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryString_Activate(entry); - - S_PlaySound(PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - } - - break; - } - } - } - - // prepare for the next line - y += height; - y += (!calculatedentryspacing || calculatedentryspacing > entry->getMarginBottom()) ? entry->getMarginBottom() : calculatedentryspacing; - } - - // draw indicators if applicable - if (actually_draw) - Menu_RunScrollbar(cm, menu->format, y_upper + totalHeight, &menu->scrollPos, 320<<16, origin); - } - - return totalHeight; -} - -static void Menu_RunOptionList(Menu_t *cm, MenuEntry_t *entry, MenuOption_t *object, const vec2_t origin) -{ - int32_t e, y = 0; - const int32_t y_upper = object->options->menuFormat->pos.y; - const int32_t y_lower = object->options->menuFormat->bottomcutoff; - int32_t calculatedentryspacing = object->options->getMarginBottom(); - - // assumes height == font->get_yline()! - if (calculatedentryspacing < 0) - calculatedentryspacing = (-calculatedentryspacing - object->options->font->get_yline()) / (object->options->numOptions - 1) - object->options->font->get_yline(); - - int32_t totalHeight = 0; - for (e = 0; e < object->options->numOptions; ++e) - { - int32_t const height = object->options->font->get_yline(); - - y += height; - totalHeight = y; - y += calculatedentryspacing; - } - y = 0; - - int32_t ydim_upper, ydim_lower; - if (y_upper + totalHeight > y_lower) - { - ydim_upper = ydim_from_200_16(origin.y + y_upper); - ydim_lower = ydim_from_200_16(origin.y + y_lower); - } - else - { - ydim_upper = 0; - ydim_lower = ydim-1; - } - - for (e = 0; e < object->options->numOptions; ++e) - { - int32_t const x = object->options->menuFormat->pos.x; - - uint8_t status = 0; - if (e == object->options->currentEntry) - status |= MT_Selected; - if (object->options->entryFormat->width == 0) - status |= MT_XCenter; - - bool const dodraw = 0 <= y - object->options->scrollPos + object->options->font->get_yline() && - y - object->options->scrollPos <= object->options->menuFormat->bottomcutoff - object->options->menuFormat->pos.y; - - int32_t const height = object->options->font->get_yline(); // max(textsize.y, object->options->font->get_yline()); - status |= MT_YCenter; - int32_t const y_internal = origin.y + y_upper + y + ((height>>17)<<16) - object->options->scrollPos; - - vec2_t textsize; - if (dodraw) - textsize = Menu_Text(origin.x + x, y_internal, object->options->font, object->options->optionNames[e], status, ydim_upper, ydim_lower); - - if (object->options->entryFormat->width < 0) - status |= MT_XRight; - - if (dodraw && (status & MT_Selected)) - { - if (status & MT_XCenter) - { - Menu_DrawCursorLeft(origin.x + (MENU_MARGIN_CENTER<<16) + object->options->font->cursorCenterPosition, y_internal, object->options->font->cursorScale); - Menu_DrawCursorRight(origin.x + (MENU_MARGIN_CENTER<<16) - object->options->font->cursorCenterPosition, y_internal, object->options->font->cursorScale); - } - else - Menu_DrawCursorLeft(origin.x + x - object->options->font->cursorLeftPosition, y_internal, object->options->font->cursorScale); - } - - if (dodraw) - { - const int32_t mousex = origin.x + object->options->entryFormat->width == 0 ? x - ((textsize.x>>17)<<16) : x; - const int32_t mousey = origin.y + y_upper + y - object->options->scrollPos; - const int32_t mousewidth = object->options->entryFormat->width == 0 ? textsize.x : klabs(object->options->entryFormat->width); - - if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, object->options->font->get_yline()))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, object->options->font->get_yline()))) - { - object->options->currentEntry = e; - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, object->options->font->get_yline())) - { - object->options->currentEntry = e; - - if (!Menu_RunInput_EntryOptionList_Activate(entry, object)) - S_PlaySound(PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - } - - // prepare for the next line - y += height; - y += calculatedentryspacing; - } - - // draw indicators if applicable - Menu_RunScrollbar(cm, object->options->menuFormat, y_upper + totalHeight, &object->options->scrollPos, 320<<16, origin); -} - -static int32_t Menu_RunInput_MouseAdvance(void) -{ - return MOUSEACTIVECONDITIONAL(!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED); -} - -static int32_t Menu_RunInput_MouseReturn_status; - -#if !defined EDUKE32_TOUCH_DEVICES -static void Menu_Run_MouseReturn(Menu_t *cm, const vec2_t origin) -{ - if (!MOUSEACTIVECONDITION) - return; - - if (cm->menuID == MENU_MAIN) - return; - - uint32_t const posx = tilesiz[SELECTDIR].y * SELECTDIR_z; - - rotatesprite_(origin.x + posx, 0, SELECTDIR_z, 512, SELECTDIR, - Menu_RunInput_MouseReturn_status ? 4 - (sintable[((int32_t) totalclock << 4) & 2047] >> 11) : 6, 0, - 2 | 8 | 16 | RS_ALIGN_L, MOUSEALPHA, 0, xdim_from_320_16(origin.x + x_widescreen_left()), 0, - xdim_from_320_16(origin.x + x_widescreen_left() + ((posx>>17)<<16)), ydim - 1); -} -#endif - -static int32_t Menu_RunInput_MouseReturn(void) -{ -#if !defined EDUKE32_TOUCH_DEVICES - if (!MOUSEACTIVECONDITION) - { - Menu_RunInput_MouseReturn_status = 0; - return 0; - } -#endif - - if (g_currentMenu == MENU_MAIN) - return 0; - - const int32_t MouseReturnRegionX = x_widescreen_left(); - - vec2_t backbuttonbound = { ((tilesiz[SELECTDIR].y * SELECTDIR_z)>>17)<<16, tilesiz[SELECTDIR].x * SELECTDIR_z }; - - if (!Menu_MouseOutsideBounds(&m_mousepos, MouseReturnRegionX, 0, backbuttonbound.x, backbuttonbound.y)) - { -#if !defined EDUKE32_TOUCH_DEVICES - Menu_RunInput_MouseReturn_status = 1; -#else - Menu_RunInput_MouseReturn_status = (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD); -#endif - - return !m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, MouseReturnRegionX, 0, backbuttonbound.x, backbuttonbound.y); - } - - Menu_RunInput_MouseReturn_status = 0; - - return 0; -} - -static void Menu_Run_AbbreviateNameIntoBuffer(const char* name, int32_t entrylength) -{ - int32_t len = Bstrlen(name); - Bstrncpy(tempbuf, name, ARRAY_SIZE(tempbuf)); - if (len > entrylength) - { - len = entrylength-3; - tempbuf[len] = 0; - while (len < entrylength) - tempbuf[len++] = '.'; - } - tempbuf[len] = 0; -} - -static void Menu_Recurse(MenuID_t cm, const vec2_t origin) -{ - switch (cm) - { - case MENU_SAVECLEANVERIFY: - case MENU_LOADVERIFY: - case MENU_LOADDELVERIFY: - case MENU_SAVEVERIFY: - case MENU_SAVEDELVERIFY: - case MENU_COLCORRRESETVERIFY: - case MENU_KEYSRESETVERIFY: - case MENU_KEYSCLASSICVERIFY: - case MENU_JOYSTANDARDVERIFY: - case MENU_JOYPROVERIFY: - case MENU_JOYCLEARVERIFY: - case MENU_ADULTPASSWORD: - case MENU_CHEATENTRY: - case MENU_CHEAT_WARP: - case MENU_CHEAT_SKILL: - Menu_Run(m_previousMenu, origin); - break; - default: - break; - } -} - -static void Menu_Run(Menu_t *cm, const vec2_t origin) -{ - Menu_Recurse(cm->menuID, origin); - - switch (cm->type) - { - case Verify: - { - auto object = (MenuVerify_t*)cm->object; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - Menu_PreDraw(cm->menuID, NULL, origin); - - Menu_DrawCursorLeft(origin.x + object->cursorpos.x, origin.y + object->cursorpos.y, 65536); - - break; - } - - case Message: - { - auto object = (MenuMessage_t*)cm->object; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - Menu_PreDraw(cm->menuID, NULL, origin); - - Menu_DrawCursorLeft(origin.x + object->cursorpos.x, origin.y + object->cursorpos.y, 65536); - - break; - } - - case TextForm: - { - auto object = (MenuTextForm_t*)cm->object; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - Menu_BlackRectangle(origin.x + (60<<16), origin.y + (86<<16), 200<<16, 28<<16, 0); - - mgametextcenter(origin.x, origin.y + (98<<16), object->instructions, TEXT_YBOTTOM); - - const char *displaytext = object->input; - - if (object->flags & MTF_Password) - { - size_t x; - for (x = 0; x < Bstrlen(object->input); ++x) - tempbuf[x] = '*'; - tempbuf[x] = 0; - - displaytext = tempbuf; - } - - const vec2_t textreturn = mgametextcenter(origin.x, origin.y + (102<<16), displaytext); - - Menu_PreDraw(cm->menuID, NULL, origin); - - int32_t const h = MF_Bluefont.get_yline(); - - Menu_DrawCursorText(origin.x + (MENU_MARGIN_CENTER<<16) + ((textreturn.x>>17)<<16) + (1<<16), origin.y + (102<<16) + ((h>>17)<<16), h); - - break; - } - - case FileSelect: - { -#if 0 - auto object = (MenuFileSelect_t*)cm->object; - const int32_t MenuFileSelect_scrollbar_rightedge[2] = { 160<<16, 284<<16 }; - int32_t i, selected = 0; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - if (object->title != NoTitle) - Menu_DrawTopBar(origin); - - - // black translucent background underneath file lists - Menu_BlackRectangle(origin.x + (36<<16), origin.y + (42<<16), 248<<16, 123<<16, 1|32); - - // path - Bsnprintf(tempbuf, sizeof(tempbuf), "Path: %s", object->destination); - mgametext(origin.x + object->format[0]->pos.x, origin.y + (32<<16), tempbuf); - - uint8_t column_status[2] = { 0, MT_RightSide }; - - for (i = 0; i < 2; ++i) - { - if (object->findhigh[i]) - { - CACHE1D_FIND_REC *dir; - int32_t y = 0; - const int32_t y_upper = object->format[i]->pos.y; - const int32_t y_lower = klabs(object->format[i]->bottomcutoff); - - int32_t totalHeight = 0; - for (dir = object->findhigh[i]->usera; dir; dir = dir->next) - { - y += object->font[i]->get_yline(); - totalHeight = y; - y += object->getMarginBottom(i); - } - y = 0; - - int32_t ydim_upper, ydim_lower; - if (y_upper + totalHeight > y_lower) - { - ydim_upper = ydim_from_200_16(origin.y + y_upper); - ydim_lower = ydim_from_200_16(origin.y + y_lower); - } - else - { - ydim_upper = 0; - ydim_lower = ydim-1; - } - - for (dir = object->findhigh[i]->usera; dir; dir = dir->next) - { - uint8_t status = column_status[i]; - if (dir == object->findhigh[i] && object->currentList == i) - status |= MT_Selected; - - // pal = dir->source==CACHE1D_SOURCE_ZIP ? 8 : 2 - - Menu_Run_AbbreviateNameIntoBuffer(dir->name, USERMAPENTRYLENGTH); - - const int32_t thisx = object->format[i]->pos.x; - const int32_t thisy = y - object->scrollPos[i]; - - int32_t const height = object->font[i]->get_yline(); - - if (0 <= thisy + height && thisy <= klabs(object->format[i]->bottomcutoff) - object->format[i]->pos.y) - { - status |= MT_YCenter; - - const int32_t mousex = origin.x + thisx; - const int32_t mousey = origin.y + y_upper + thisy + ((height>>17)<<16); - - vec2_t textdim = Menu_Text(mousex, mousey, object->font[i], tempbuf, status, ydim_upper, ydim_lower); - - if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, textdim.x, object->font[i]->get_yline()))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, textdim.x, object->font[i]->get_yline()))) - { - object->findhigh[i] = dir; - object->currentList = i; - - Menu_RunInput_FileSelect_MovementVerify(object); - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, textdim.x, object->font[i]->get_yline())) - { - object->findhigh[i] = dir; - object->currentList = i; - - Menu_RunInput_FileSelect_MovementVerify(object); - - m_mousecaught = 1; - selected = 1; - } - } - } - - y += object->font[i]->get_yline() + object->getMarginBottom(i); - } - - Menu_RunScrollbar(cm, object->format[i], y_upper + totalHeight, &object->scrollPos[i], MenuFileSelect_scrollbar_rightedge[i], origin); - } - } - - Menu_PreDraw(cm->menuID, NULL, origin); - - if (object->title != NoTitle) - Menu_DrawTopBarCaption(object->title, origin); - - if (selected) - { - Menu_RunInput_FileSelect_Select(object); - - S_PlaySound(PISTOL_BODYHIT); - - m_mousecaught = 1; - } -#endif - break; - } - - case Panel: - { - auto object = (MenuPanel_t*)cm->object; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - if (object->title != NoTitle) - Menu_DrawTopBar(origin); - - Menu_PreDraw(cm->menuID, NULL, origin); - - if (object->title != NoTitle) - Menu_DrawTopBarCaption(object->title, origin); - - break; - } - - case Menu: - { - int32_t state; - - auto menu = (MenuMenu_t*)cm->object; - MenuEntry_t *currentry = menu->entrylist[menu->currentEntry]; - - state = Menu_DetermineSpecialState(currentry); - - if (state != 2) - { - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - if (menu->title != NoTitle) - Menu_DrawTopBar(origin); - - Menu_PreDraw(cm->menuID, currentry, origin); - - M_RunMenu_Menu(cm, menu, currentry, state, origin); - } - else - { - Menu_PreDrawBackground(cm->menuID, origin); - - if (menu->title != NoTitle) - Menu_DrawTopBar(origin); - - if (currentry->type == Option) - { - if (currentry->name) - Menu_DrawTopBarCaption(currentry->name, origin); - - Menu_PreOptionListDraw(currentry, origin); - - Menu_RunOptionList(cm, currentry, (MenuOption_t*)currentry->entry, origin); - } - else if (currentry->type == Custom2Col) - { - Menu_PreCustom2ColScreenDraw(currentry, origin); - } - } - - if ((currentry->type != Option || state != 2) && menu->title != NoTitle) - Menu_DrawTopBarCaption(menu->title, origin); - - break; - } - } - -#if !defined EDUKE32_TOUCH_DEVICES - Menu_Run_MouseReturn(cm, origin); -#endif -} - -/* -Note: When menus are exposed to scripting, care will need to be taken so that -a user cannot define an empty MenuEntryList, or one containing only spacers, -or else this function will recurse infinitely. -*/ -static MenuEntry_t *Menu_RunInput_Menu_MovementVerify(MenuMenu_t *menu) -{ - return Menu_AdjustForCurrentEntryAssignment(menu); -} - -static MenuEntry_t *Menu_RunInput_Menu_Movement(MenuMenu_t *menu, MenuMovement_t direction) -{ - if (menu->numEntries == 1) - return menu->entrylist[menu->currentEntry]; - - switch (direction) - { - case MM_End: - menu->currentEntry = menu->numEntries; - fallthrough__; - case MM_Up: - do - { - --menu->currentEntry; - if (menu->currentEntry < 0) - return Menu_RunInput_Menu_Movement(menu, MM_End); - } - while (!menu->entrylist[menu->currentEntry] || - (menu->entrylist[menu->currentEntry]->flags & MEF_Hidden) || - menu->entrylist[menu->currentEntry]->type == Spacer); - break; - - case MM_Home: - menu->currentEntry = -1; - fallthrough__; - case MM_Down: - do - { - ++menu->currentEntry; - if (menu->currentEntry >= menu->numEntries) - return Menu_RunInput_Menu_Movement(menu, MM_Home); - } - while (!menu->entrylist[menu->currentEntry] || - (menu->entrylist[menu->currentEntry]->flags & MEF_Hidden) || - menu->entrylist[menu->currentEntry]->type == Spacer); - break; - - case MM_Swap: - menu->currentColumn = !menu->currentColumn; - break; - - default: - break; - } - - return Menu_RunInput_Menu_MovementVerify(menu); -} - -static void Menu_RunInput_EntryLink_Activate(MenuEntry_t *entry) -{ - auto link = (MenuLink_t*)entry->entry; - - Menu_EntryLinkActivate(entry); - - Menu_AnimateChange(link->linkID, link->animation); -} - -static void Menu_RunInput_EntryOptionList_MovementVerify(MenuOption_t *object) -{ - const int32_t listytop = object->options->menuFormat->pos.y; - // assumes height == font->get_yline()! - const int32_t unitheight = object->options->getMarginBottom() < 0 ? (-object->options->getMarginBottom() - object->options->font->get_yline()) / object->options->numOptions : (object->options->font->get_yline() + object->options->getMarginBottom()); - const int32_t ytop = listytop + object->options->currentEntry * unitheight; - const int32_t ybottom = ytop + object->options->font->get_yline(); - - if (ybottom - object->options->scrollPos > object->options->menuFormat->bottomcutoff) - object->options->scrollPos = ybottom - object->options->menuFormat->bottomcutoff; - else if (ytop - object->options->scrollPos < listytop) - object->options->scrollPos = ytop - listytop; -} - -static void Menu_RunInput_EntryOptionList_Movement(MenuOption_t *object, MenuMovement_t direction) -{ - switch (direction) - { - case MM_Up: - --object->options->currentEntry; - if (object->options->currentEntry >= 0) - break; - fallthrough__; - case MM_End: - object->options->currentEntry = object->options->numOptions-1; - break; - - case MM_Down: - ++object->options->currentEntry; - if (object->options->currentEntry < object->options->numOptions) - break; - fallthrough__; - case MM_Home: - object->options->currentEntry = 0; - break; - - default: - break; - } - - Menu_RunInput_EntryOptionList_MovementVerify(object); -} - -static int32_t Menu_RunInput_EntryOption_Modify(MenuEntry_t *entry, MenuOption_t *object, int32_t newValueIndex) -{ - int32_t newValue = (object->options->optionValues == NULL) ? newValueIndex : object->options->optionValues[newValueIndex]; - if (!Menu_EntryOptionModify(entry, newValue)) - { - object->currentOption = newValueIndex; - - if (object->cVar != NULL) // NULL implies the functions will handle it - { - UCVarValue v; - v.Int = newValue; - object->cVar->ForceSet(v, CVAR_Int, false); - } - Menu_EntryOptionDidModify(entry); - - return 0; - } - - return -1; -} - -static int32_t Menu_RunInput_EntryOption_Movement(MenuEntry_t *entry, MenuOption_t *object, MenuMovement_t direction) -{ - int32_t newValueIndex = object->currentOption; - - switch (direction) - { - case MM_Left: - --newValueIndex; - if (newValueIndex >= 0) - break; - fallthrough__; - case MM_AllTheWayRight: - newValueIndex = object->options->numOptions-1; - break; - - case MM_Right: - ++newValueIndex; - if (newValueIndex < object->options->numOptions) - break; - fallthrough__; - case MM_AllTheWayLeft: - newValueIndex = 0; - break; - - default: - break; - } - - return Menu_RunInput_EntryOption_Modify(entry, object, newValueIndex); -} - -static int32_t Menu_RunInput_EntryOption_Activate(MenuEntry_t *entry, MenuOption_t *object) -{ - if (object->options->features & 2) - return Menu_RunInput_EntryOption_Movement(entry, object, MM_Right); - else - { - object->options->currentEntry = object->currentOption >= 0 ? object->currentOption : 0; - Menu_RunInput_EntryOptionList_MovementVerify(object); - - return 0; - } -} - -static int32_t Menu_RunInput_EntryOptionList_Activate(MenuEntry_t *entry, MenuOption_t *object) -{ - if (!Menu_RunInput_EntryOption_Modify(entry, object, object->options->currentEntry)) - { - object->options->currentEntry = -1; - - return 0; - } - - return -1; -} - -static void Menu_RunInput_EntryCustom2Col_Activate(MenuEntry_t *entry) -{ - auto object = (MenuCustom2Col_t*)entry->entry; - - Menu_Custom2ColScreen(/*entry*/); - - object->screenOpen = 1; -} - -static void Menu_RunInput_EntryRangeInt32_MovementVerify(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue) -{ - if (!Menu_EntryRangeInt32Modify(entry, newValue)) - *object->cVar = newValue; -} - -static void Menu_RunInput_EntryRangeInt32_MovementArbitrary(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue) -{ - if (object->flags & EnforceIntervals) - { - int32_t const range = object->max - object->min; - int32_t const maxInterval = object->steps - 1; - int32_t const newValueIndex = roundscale(newValue - object->min, maxInterval, range); - newValue = newValueIndex * range / maxInterval + object->min; - } - - Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, newValue); -} - -static void Menu_RunInput_EntryRangeInt32_Movement(MenuEntry_t *entry, MenuRangeInt32_t *object, MenuMovement_t direction) -{ - int32_t const oldValue = *object->cVar; - int32_t const range = object->max - object->min; - int32_t const maxInterval = object->steps - 1; - int32_t const oldValueIndex = roundscale(oldValue - object->min, maxInterval, range); - int32_t const oldValueQuantized = oldValueIndex * range / maxInterval + object->min; - int32_t newValueIndex = oldValueIndex; - - switch (direction) - { - case MM_Left: - if (oldValueQuantized >= oldValue) - --newValueIndex; - if (newValueIndex >= 0) - break; - fallthrough__; - case MM_AllTheWayLeft: - newValueIndex = 0; - break; - - case MM_Right: - if (oldValueQuantized <= oldValue) - ++newValueIndex; - if (newValueIndex <= maxInterval) - break; - fallthrough__; - case MM_AllTheWayRight: - newValueIndex = maxInterval; - break; - - default: - break; - } - - int32_t const newValue = newValueIndex * range / maxInterval + object->min; - Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, newValue); -} - -static void Menu_RunInput_EntryRangeFloat_MovementVerify(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue) -{ - if (!Menu_EntryRangeFloatModify(entry, newValue)) - { - *object->cVar = newValue; - Menu_EntryRangeFloatDidModify(entry); - } -} - -static void Menu_RunInput_EntryRangeFloat_MovementArbitrary(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue) -{ - if (object->flags & EnforceIntervals) - { - float const range = object->max - object->min; - float const maxInterval = (float)(object->steps - 1); - float const newValueIndex = rintf((newValue - object->min) * maxInterval / range); - newValue = newValueIndex * range / maxInterval + object->min; - } - - Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, newValue); -} - -static void Menu_RunInput_EntryRangeFloat_Movement(MenuEntry_t *entry, MenuRangeFloat_t *object, MenuMovement_t direction) -{ - float const oldValue = *object->cVar; - float const range = object->max - object->min; - float const maxInterval = (float)(object->steps - 1); - float const oldValueIndexUnrounded = (oldValue - object->min) * maxInterval / range; - float const oldValueIndex = rintf(oldValueIndexUnrounded); - float const oldValueQuantized = oldValueIndex * range / maxInterval + object->min; - float newValueIndex = oldValueIndex; - - switch (direction) - { - case MM_Left: - if (oldValueQuantized >= oldValue) - newValueIndex -= 1.f; - if (newValueIndex >= 0.f) - break; - fallthrough__; - case MM_AllTheWayLeft: - newValueIndex = 0.f; - break; - - case MM_Right: - if (oldValueQuantized <= oldValue) - newValueIndex += 1.f; - if (newValueIndex <= maxInterval) - break; - fallthrough__; - case MM_AllTheWayRight: - newValueIndex = maxInterval; - break; - - default: - break; - } - - float const newValue = newValueIndex * range / maxInterval + object->min; - Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, newValue); -} - -#ifdef MENU_ENABLE_RANGEDOUBLE -static void Menu_RunInput_EntryRangeDouble_MovementVerify(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue) -{ - if (!Menu_EntryRangeDoubleModify(/*entry, newValue*/)) - *object->variable = newValue; -} - -static void Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue) -{ - if (object->flags & EnforceIntervals) - { - double const range = object->max - object->min; - double const maxInterval = object->steps - 1; - double const newValueIndex = rint((newValue - object->min) * maxInterval / range); - newValue = newValueIndex * range / maxInterval + object->min; - } - - Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, newValue); -} - -static void Menu_RunInput_EntryRangeDouble_Movement(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, MenuMovement_t direction) -{ - double const oldValue = *object->variable; - double const range = object->max - object->min; - double const maxInterval = object->steps - 1; - double const oldValueIndex = rint((oldValue - object->min) * maxInterval / range); - double const oldValueQuantized = oldValueIndex * range / maxInterval + object->min; - double newValueIndex = oldValueIndex; - - switch (direction) - { - case MM_Left: - if (oldValueQuantized >= oldValue) - newValueIndex -= 1.; - if (newValueIndex >= 0.) - break; - fallthrough__; - case MM_AllTheWayLeft: - newValueIndex = 0.; - break; - - case MM_Right: - if (oldValueQuantized <= oldValue) - newValueIndex += 1.; - if (newValueIndex <= maxInterval) - break; - fallthrough__; - case MM_AllTheWayRight: - newValueIndex = maxInterval; - break; - - default: - break; - } - - double const newValue = newValueIndex * range / maxInterval + object->min; - Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, newValue); -} -#endif - -static void Menu_RunInput_EntryString_Activate(MenuEntry_t *entry) -{ - auto object = (MenuString_t*)entry->entry; - - if (object->variable) - strncpy(typebuf, object->variable, TYPEBUFSIZE); - else - typebuf[0] = '\0'; - object->editfield = typebuf; - - // this limitation is an arbitrary implementation detail - if (object->bufsize > TYPEBUFSIZE) - object->bufsize = TYPEBUFSIZE; - - Menu_EntryStringActivate(/*entry*/); - Menu_StartTextInput(); -} - -static void Menu_RunInput_EntryString_Submit(/*MenuEntry_t *entry, */MenuString_t *object) -{ - if (!Menu_EntryStringSubmit(/*entry, */object->editfield)) - { - if (object->variable) - strncpy(object->variable, object->editfield, object->bufsize); - } - - object->editfield = NULL; - Menu_StopTextInput(); -} - -static void Menu_RunInput_EntryString_Cancel(/*MenuEntry_t *entry, */MenuString_t *object) -{ - Menu_EntryStringCancel(/*entry*/); - - object->editfield = NULL; - Menu_StopTextInput(); -} - -static void Menu_RunInput_FileSelect_MovementVerify(MenuFileSelect_t *object) -{ -#if 0 - const int32_t listytop = object->format[object->currentList]->pos.y; - const int32_t listybottom = klabs(object->format[object->currentList]->bottomcutoff); - const int32_t ytop = listytop + object->findhigh[object->currentList]->type * (object->font[object->currentList]->get_yline() + object->getMarginBottom(object->currentList)); - const int32_t ybottom = ytop + object->font[object->currentList]->get_yline(); - - if (ybottom - object->scrollPos[object->currentList] > listybottom) - object->scrollPos[object->currentList] = ybottom - listybottom; - else if (ytop - object->scrollPos[object->currentList] < listytop) - object->scrollPos[object->currentList] = ytop - listytop; -#endif -} - -static void Menu_RunInput_FileSelect_Movement(MenuFileSelect_t *object, MenuMovement_t direction) -{ -#if 0 - switch (direction) - { - case MM_Up: - if (!object->findhigh[object->currentList]) - break; - if (object->findhigh[object->currentList]->prev) - { - object->findhigh[object->currentList] = object->findhigh[object->currentList]->prev; - break; - } - fallthrough__; - case MM_End: - object->findhigh[object->currentList] = object->findhigh[object->currentList]->userb; - break; - - case MM_Down: - if (!object->findhigh[object->currentList]) - break; - if (object->findhigh[object->currentList]->next) - { - object->findhigh[object->currentList] = object->findhigh[object->currentList]->next; - break; - } - fallthrough__; - case MM_Home: - object->findhigh[object->currentList] = object->findhigh[object->currentList]->usera; - break; - - case MM_Swap: - object->currentList = !object->currentList; - break; - - default: - break; - } - - Menu_RunInput_FileSelect_MovementVerify(object); -#endif -} - -static void Menu_RunInput_FileSelect_Select(MenuFileSelect_t *object) -{ -#if 0 - if (!object->findhigh[object->currentList]) - return; - - Bstrcat(object->destination, object->findhigh[object->currentList]->name); - - if (object->currentList == 0) - { - Bstrcat(object->destination, "/"); - Bcorrectfilename(object->destination, 1); - - Menu_FileSelectInit(object); - } - else - { - Menu_FileSelect(1); - } -#endif -} - -static void Menu_RunInput(Menu_t *cm) -{ - switch (cm->type) - { - case Panel: - { - auto panel = (MenuPanel_t*)cm->object; - - if (I_ReturnTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - } - else if (I_PanelUp()) - { - I_PanelUpClear(); - - S_PlaySound(KICK_HIT); - Menu_AnimateChange(panel->previousID, panel->previousAnimation); - } - else if (I_PanelDown() || Menu_RunInput_MouseAdvance()) - { - I_PanelDownClear(); - m_mousecaught = 1; - - S_PlaySound(KICK_HIT); - Menu_AnimateChange(panel->nextID, panel->nextAnimation); - } - break; - } - - case TextForm: - { - auto object = (MenuTextForm_t*)cm->object; - int32_t hitstate = I_EnterText(object->input, object->bufsize-1, 0); - - if (hitstate == -1 || Menu_RunInput_MouseReturn()) - { - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - object->input = NULL; - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - Menu_StopTextInput(); - } - else if (hitstate == 1 || Menu_RunInput_MouseAdvance()) - { - m_mousecaught = 1; - - Menu_TextFormSubmit(object->input); - - object->input = NULL; - Menu_StopTextInput(); - } - break; - } - - case FileSelect: - { -#if 0 - auto object = (MenuFileSelect_t*)cm->object; - - if (I_ReturnTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - object->destination[0] = 0; - - Menu_FileSelect(0); - - Menu_AnimateChange(cm->parentID, MA_Return); - } - else if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_FileSelect_Select(object); - - S_PlaySound(PISTOL_BODYHIT); - } - else if (inputState.GetKeyStatus(sc_Home)) - { - inputState.ClearKeyStatus(sc_Home); - - Menu_RunInput_FileSelect_Movement(object, MM_Home); - - S_PlaySound(KICK_HIT); - } - else if (inputState.GetKeyStatus(sc_End)) - { - inputState.ClearKeyStatus(sc_End); - - Menu_RunInput_FileSelect_Movement(object, MM_End); - - S_PlaySound(KICK_HIT); - } - else if (inputState.GetKeyStatus(sc_PgUp)) - { - int32_t i; - - CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList]; - - inputState.ClearKeyStatus(sc_PgUp); - - for (i = 0; i < 6; ++i) - { - if (seeker && seeker->prev) - seeker = seeker->prev; - } - - if (seeker) - { - object->findhigh[object->currentList] = seeker; - - Menu_RunInput_FileSelect_MovementVerify(object); - - S_PlaySound(KICK_HIT); - } - } - else if (inputState.GetKeyStatus(sc_PgDn)) - { - int32_t i; - - CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList]; - - inputState.ClearKeyStatus(sc_PgDn); - - for (i = 0; i < 6; ++i) - { - if (seeker && seeker->next) - seeker = seeker->next; - } - - if (seeker) - { - object->findhigh[object->currentList] = seeker; - - Menu_RunInput_FileSelect_MovementVerify(object); - - S_PlaySound(KICK_HIT); - } - } - else if (I_MenuLeft() || I_MenuRight()) - { - I_MenuLeftClear(); - I_MenuRightClear(); - - if ((object->currentList ? object->fnlist.numdirs : object->fnlist.numfiles) > 0) - { - Menu_RunInput_FileSelect_Movement(object, MM_Swap); - - S_PlaySound(KICK_HIT); - } - } - else if (I_MenuUp()) - { - I_MenuUpClear(); - - Menu_RunInput_FileSelect_Movement(object, MM_Up); - - S_PlaySound(KICK_HIT); - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - - Menu_RunInput_FileSelect_Movement(object, MM_Down); - - S_PlaySound(KICK_HIT); - } - else - { - // JBF 20040208: seek to first name matching pressed character - char ch2, ch; - ch = inputState.keyGetChar(); - if (ch > 0 && ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))) - { - CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList]->usera; - if (ch >= 'a') - ch -= ('a'-'A'); - while (seeker) - { - ch2 = seeker->name[0]; - if (ch2 >= 'a' && ch2 <= 'z') - ch2 -= ('a'-'A'); - if (ch2 == ch) - break; - seeker = seeker->next; - } - if (seeker) - { - object->findhigh[object->currentList] = seeker; - - Menu_RunInput_FileSelect_MovementVerify(object); - - S_PlaySound(KICK_HIT); - } - } - } -#endif - Menu_PreInput(NULL); - break; - } - - case Message: - if (I_ReturnTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - } - - if (I_CheckAllInput()) - { - auto message = (MenuMessage_t*)cm->object; - - I_ClearAllInput(); - - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(message->linkID, message->animation); - } - - Menu_PreInput(NULL); - break; - - case Verify: - if (I_ReturnTrigger() || inputState.GetKeyStatus(sc_N) || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - inputState.ClearKeyStatus(sc_N); - m_mousecaught = 1; - - Menu_Verify(0); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - - S_PlaySound(EXITMENUSOUND); - } - - if (I_AdvanceTrigger() || inputState.GetKeyStatus(sc_Y) || Menu_RunInput_MouseAdvance()) - { - auto verify = (MenuVerify_t*)cm->object; - - I_AdvanceTriggerClear(); - inputState.ClearKeyStatus(sc_Y); - m_mousecaught = 1; - - Menu_Verify(1); - - Menu_AnimateChange(verify->linkID, verify->animation); - - S_PlaySound(PISTOL_BODYHIT); - } - - Menu_PreInput(NULL); - break; - - case Menu: - { - int32_t state; - - auto menu = (MenuMenu_t*)cm->object; - MenuEntry_t *currentry = menu->entrylist[menu->currentEntry]; - - state = Menu_DetermineSpecialState(currentry); - - if (state == 0) - { - if (currentry != NULL) - switch (currentry->type) - { - case Dummy: - case Spacer: - break; - case Link: - if (currentry->flags & MEF_Disabled) - break; - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_EntryLink_Activate(currentry); - - if (g_player[myconnectindex].ps->gm&MODE_MENU) // for skill selection - S_PlaySound(PISTOL_BODYHIT); - } - break; - case Option: - { - auto object = (MenuOption_t*)currentry->entry; - - if (currentry->flags & MEF_Disabled) - break; - - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_EntryOption_Activate(currentry, object); - - S_PlaySound(PISTOL_BODYHIT); - } - else if (I_MenuRight()) - { - I_MenuRightClear(); - - Menu_RunInput_EntryOption_Movement(currentry, object, MM_Right); - - S_PlaySound(PISTOL_BODYHIT); - } - else if (I_MenuLeft()) - { - I_MenuLeftClear(); - - Menu_RunInput_EntryOption_Movement(currentry, object, MM_Left); - - S_PlaySound(PISTOL_BODYHIT); - } - } - break; - case Custom2Col: - if (I_MenuLeft() || I_MenuRight()) - { - I_MenuLeftClear(); - I_MenuRightClear(); - - Menu_RunInput_Menu_Movement(menu, MM_Swap); - - S_PlaySound(KICK_HIT); - } - - if (currentry->flags & MEF_Disabled) - break; - - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_EntryCustom2Col_Activate(currentry); - - S_PlaySound(PISTOL_BODYHIT); - } - break; - case RangeInt32: - { - auto object = (MenuRangeInt32_t*)currentry->entry; - - if (currentry->flags & MEF_Disabled) - break; - - if (I_SliderLeft()) - { - I_SliderLeftClear(); - - Menu_RunInput_EntryRangeInt32_Movement(currentry, object, MM_Left); - - S_PlaySound(KICK_HIT); - } - else if (I_SliderRight()) - { - I_SliderRightClear(); - - Menu_RunInput_EntryRangeInt32_Movement(currentry, object, MM_Right); - - S_PlaySound(KICK_HIT); - } - break; - } - case RangeFloat: - { - auto object = (MenuRangeFloat_t*)currentry->entry; - - if (currentry->flags & MEF_Disabled) - break; - - if (I_SliderLeft()) - { - I_SliderLeftClear(); - - Menu_RunInput_EntryRangeFloat_Movement(currentry, object, MM_Left); - - S_PlaySound(KICK_HIT); - } - else if (I_SliderRight()) - { - I_SliderRightClear(); - - Menu_RunInput_EntryRangeFloat_Movement(currentry, object, MM_Right); - - S_PlaySound(KICK_HIT); - } - break; - } -#ifdef MENU_ENABLE_RANGEDOUBLE - case RangeDouble: - { - MenuRangeDouble_t *object = (MenuRangeDouble_t*)currentry->entry; - - if (currentry->flags & MEF_Disabled) - break; - - if (I_SliderLeft()) - { - I_SliderLeftClear(); - - Menu_RunInput_EntryRangeDouble_Movement(/*currentry, */object, MM_Left); - - S_PlaySound(KICK_HIT); - } - else if (I_SliderRight()) - { - I_SliderRightClear(); - - Menu_RunInput_EntryRangeDouble_Movement(/*currentry, */object, MM_Right); - - S_PlaySound(KICK_HIT); - } - break; - } -#endif - - case String: - { - if (currentry->flags & MEF_Disabled) - break; - - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_EntryString_Activate(currentry); - - S_PlaySound(PISTOL_BODYHIT); - } - - break; - } - } - - if (I_ReturnTrigger() || I_EscapeTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - I_EscapeTriggerClear(); - m_mousecaught = 1; - - if (cm->parentID != MENU_CLOSE || (g_player[myconnectindex].ps->gm & MODE_GAME)) - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - } - else if (inputState.GetKeyStatus(sc_Home)) - { - inputState.ClearKeyStatus(sc_Home); - - S_PlaySound(KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_Home); - } - else if (inputState.GetKeyStatus(sc_End)) - { - inputState.ClearKeyStatus(sc_End); - - S_PlaySound(KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_End); - } - else if (I_MenuUp()) - { - I_MenuUpClear(); - - S_PlaySound(KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_Up); - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - - S_PlaySound(KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_Down); - } - - if (currentry != NULL) - Menu_PreInput(currentry); - } - else if (state == 1) - { - if (currentry->type == String) - { - auto object = (MenuString_t*)currentry->entry; - - int32_t hitstate = I_EnterText(object->editfield, object->bufsize-1, object->flags); - - if (hitstate == -1 || Menu_RunInput_MouseReturn()) - { - m_mousecaught = 1; - - Menu_RunInput_EntryString_Cancel(/*currentry, */object); - - S_PlaySound(EXITMENUSOUND); - } - else if (hitstate == 1) - { - Menu_RunInput_EntryString_Submit(/*currentry, */object); - - S_PlaySound(PISTOL_BODYHIT); - } - } - } - else if (state == 2) - { - if (currentry->type == Option) - { - auto object = (MenuOption_t*)currentry->entry; - - if (I_ReturnTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - object->options->currentEntry = -1; - } - else if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - if (!Menu_RunInput_EntryOptionList_Activate(currentry, object)) - S_PlaySound(PISTOL_BODYHIT); - } - else if (inputState.GetKeyStatus(sc_Home)) - { - inputState.ClearKeyStatus(sc_Home); - - S_PlaySound(KICK_HIT); - - Menu_RunInput_EntryOptionList_Movement(object, MM_Home); - } - else if (inputState.GetKeyStatus(sc_End)) - { - inputState.ClearKeyStatus(sc_End); - - S_PlaySound(KICK_HIT); - - Menu_RunInput_EntryOptionList_Movement(object, MM_End); - } - else if (I_MenuUp()) - { - I_MenuUpClear(); - - S_PlaySound(KICK_HIT); - - Menu_RunInput_EntryOptionList_Movement(object, MM_Up); - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - - S_PlaySound(KICK_HIT); - - Menu_RunInput_EntryOptionList_Movement(object, MM_Down); - } - } - else if (currentry->type == Custom2Col) - { - if (I_EscapeTrigger() || Menu_RunInput_MouseReturn()) - { - I_EscapeTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - ((MenuCustom2Col_t*)currentry->entry)->screenOpen = 0; - } - else if (Menu_PreCustom2ColScreen(currentry)) - ((MenuCustom2Col_t*)currentry->entry)->screenOpen = 0; - } - } - - break; - } - } -} - -void M_DisplayMenus(void) -{ - vec2_t origin = { 0, 0 }, previousOrigin = { 0, 0 }; - - Net_GetPackets(); - - if ((g_player[myconnectindex].ps->gm&MODE_MENU) == 0) - { - return; - } - - if (!Menu_IsTextInput(m_currentMenu) && inputState.GetKeyStatus(sc_Q)) - Menu_AnimateChange(MENU_QUIT, MA_Advance); - - int32_t mousestatus = inputState.mouseReadAbs(&m_mousepos); - if (mousestatus && inputState.mouseClickState() == MOUSE_PRESSED) - m_mousedownpos = m_mousepos; - - Menu_RunInput(m_currentMenu); - - g_player[myconnectindex].ps->gm &= (0xff-MODE_TYPE); - // g_player[myconnectindex].ps->fta = 0; - - int32_t const backgroundOK = ud.menubackground && Menu_BlackTranslucentBackgroundOK(g_currentMenu); - - // need EVENT_DISPLAYMENUBACKGROUND here - - if (!FURY && ((g_player[myconnectindex].ps->gm&MODE_GAME) || ud.recstat==2) && backgroundOK) - videoFadeToBlack(1); - - if (Menu_UpdateScreenOK(g_currentMenu)) - G_UpdateScreenArea(); - -#if !defined EDUKE32_TOUCH_DEVICES - if (m_menuchange_watchpoint > 0) - m_menuchange_watchpoint++; -#endif - - if (m_parentMenu) - { - ud.returnvar[0] = origin.x; - ud.returnvar[1] = origin.y; - if (m_parentMenu->type == Menu) - { - ud.returnvar[2] = ((MenuMenu_t *)m_parentMenu->object)->currentEntry; - if (m_parentMenu->menuID == MENU_NEWGAMECUSTOMSUB) - ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; - } - VM_OnEventWithReturn(EVENT_DISPLAYINACTIVEMENU, g_player[screenpeek].ps->i, screenpeek, m_parentMenu->menuID); - origin.x = ud.returnvar[0]; - origin.y = ud.returnvar[1]; - } - - // Determine animation values. - if (totalclock < m_animation.start + m_animation.length) - { - const int32_t screenwidth = scale(240<<16, xdim, ydim); - - origin.x = mulscale15(screenwidth, m_animation.in(&m_animation)); - previousOrigin.x = mulscale15(screenwidth, m_animation.out(&m_animation)); - - ud.returnvar[0] = previousOrigin.x; - ud.returnvar[1] = previousOrigin.y; - if (m_animation.previous->type == Menu) - { - ud.returnvar[2] = ((MenuMenu_t *)m_animation.previous->object)->currentEntry; - if (m_animation.previous->menuID == MENU_NEWGAMECUSTOMSUB) - ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; - } - VM_OnEventWithReturn(EVENT_DISPLAYINACTIVEMENU, g_player[screenpeek].ps->i, screenpeek, m_animation.previous->menuID); - previousOrigin.x = ud.returnvar[0]; - previousOrigin.y = ud.returnvar[1]; - } - - ud.returnvar[0] = origin.x; - ud.returnvar[1] = origin.y; - if (m_currentMenu->type == Menu) - { - ud.returnvar[2] = ((MenuMenu_t *)m_currentMenu->object)->currentEntry; - if (g_currentMenu == MENU_NEWGAMECUSTOMSUB) - ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; - } - VM_OnEventWithReturn(EVENT_DISPLAYMENU, g_player[screenpeek].ps->i, screenpeek, g_currentMenu); - origin.x = ud.returnvar[0]; - origin.y = ud.returnvar[1]; - - if (m_parentMenu && backgroundOK) - { - Menu_Run(m_parentMenu, origin); - } - - // hack; need EVENT_DISPLAYMENUBACKGROUND above - if (FURY && ((g_player[myconnectindex].ps->gm&MODE_GAME) || ud.recstat==2 || m_parentMenu != NULL) && backgroundOK) - videoFadeToBlack(1); - - // Display the menu, with a transition animation if applicable. - if (totalclock < m_animation.start + m_animation.length) - { - Menu_Run(m_animation.previous, previousOrigin); - Menu_Run(m_animation.current, origin); - } - else - Menu_Run(m_currentMenu, origin); - -#if !defined EDUKE32_TOUCH_DEVICES - if (m_menuchange_watchpoint >= 3) - m_menuchange_watchpoint = 0; -#endif - - if (m_parentMenu) - { - ud.returnvar[0] = origin.x; - ud.returnvar[1] = origin.y; - if (m_parentMenu->type == Menu) - { - ud.returnvar[2] = ((MenuMenu_t *)m_parentMenu->object)->currentEntry; - if (m_parentMenu->menuID == MENU_NEWGAMECUSTOMSUB) - ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; - } - VM_OnEventWithReturn(EVENT_DISPLAYINACTIVEMENUREST, g_player[screenpeek].ps->i, screenpeek, m_parentMenu->menuID); - } - - if (totalclock < m_animation.start + m_animation.length) - { - ud.returnvar[0] = previousOrigin.x; - ud.returnvar[1] = previousOrigin.y; - if (m_animation.previous->type == Menu) - { - ud.returnvar[2] = ((MenuMenu_t *)m_animation.previous->object)->currentEntry; - if (m_animation.previous->menuID == MENU_NEWGAMECUSTOMSUB) - ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; - } - VM_OnEventWithReturn(EVENT_DISPLAYINACTIVEMENUREST, g_player[screenpeek].ps->i, screenpeek, m_animation.previous->menuID); - } - - ud.returnvar[0] = origin.x; - ud.returnvar[1] = origin.y; - if (m_currentMenu->type == Menu) - { - ud.returnvar[2] = ((MenuMenu_t *)m_currentMenu->object)->currentEntry; - if (g_currentMenu == MENU_NEWGAMECUSTOMSUB) - ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; - } - VM_OnEventWithReturn(EVENT_DISPLAYMENUREST, g_player[screenpeek].ps->i, screenpeek, g_currentMenu); - - if (GUICapture & 2) - { - ImGui_Begin_Frame(); - bool b = true; - videoFadeToBlack(1); -#if 0 - ImGui::ShowDemoWindow(&b); - if (!b) -#else - if (!ShowOptionMenu()) -#endif - { - GUICapture &= ~2; - GUICapture |= 4; - } - return; - } - - -#if !defined EDUKE32_TOUCH_DEVICES - if (tilesiz[CROSSHAIR].x > 0 && mousestatus) -#else - if (mousestatus) -#endif - { -#if !defined EDUKE32_TOUCH_DEVICES - if (!MOUSEACTIVECONDITION) - m_mousewake_watchpoint = 1; -#endif - - if (MOUSEACTIVECONDITIONAL(inputState.mouseAdvanceClickState()) || m_mousepos.x != m_prevmousepos.x || m_mousepos.y != m_prevmousepos.y) - { - m_prevmousepos = m_mousepos; - m_mouselastactivity = (int32_t) totalclock; - } -#if !defined EDUKE32_TOUCH_DEVICES - else - m_mousewake_watchpoint = 0; -#endif - - m_mousecaught = 0; - } - else - { - m_mouselastactivity = -M_MOUSETIMEOUT; - -#if !defined EDUKE32_TOUCH_DEVICES - m_mousewake_watchpoint = 0; -#endif - } - -#ifndef EDUKE32_TOUCH_DEVICES - // Display the mouse cursor, except on touch devices. - if (MOUSEACTIVECONDITION) - { - if (VM_HaveEvent(EVENT_DISPLAYCURSOR)) - { - ud.returnvar[0] = m_mousepos.x; - ud.returnvar[1] = m_mousepos.y; - ud.returnvar[2] = CURSORALPHA; - } - int32_t a = VM_OnEventWithReturn(EVENT_DISPLAYCURSOR, g_player[screenpeek].ps->i, screenpeek, CROSSHAIR); - - if ((unsigned) a < MAXTILES) - { - vec2_t cursorpos = m_mousepos; - int32_t z = 65536; - uint8_t p = CROSSHAIR_PAL; - uint32_t o = 2|8; - - auto const oyxaspect = yxaspect; - int32_t alpha; - if (FURY) - { - renderSetAspect(viewingrange, 65536); - cursorpos.x = scale(cursorpos.x - (320<<15), ydim << 2, xdim * 3) + (320<<15); - cursorpos.y = scale(cursorpos.y - (200<<15), (ydim << 2) * 6, (xdim * 3) * 5) + (200<<15); - z = scale(32768, ydim << 2, xdim * 3); - p = 0; - o |= 1024; - alpha = MOUSEALPHA; - } - else - { - alpha = CURSORALPHA; - } - - rotatesprite_fs_alpha(cursorpos.x, cursorpos.y, z, 0, a, 0, p, o, alpha); - - if (FURY) - renderSetAspect(viewingrange, oyxaspect); - } - } - else - inputState.clearMouseClickState(); -#endif - - if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU) - { - G_UpdateScreenArea(); - CAMERACLOCK = (int32_t) totalclock; - CAMERADIST = 65536; - } -} - -bool GameInterface::mouseInactiveConditional(bool condition) -{ - return MOUSEINACTIVECONDITIONAL(condition); -} END_DUKE_NS diff --git a/source/duke3d/src/menus.h b/source/duke3d/src/menus.h index 4ec5c6e3f..fe29b6b3b 100644 --- a/source/duke3d/src/menus.h +++ b/source/duke3d/src/menus.h @@ -27,63 +27,93 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_DUKE_NS +// a subset of screentext parameters, restricted because menus require accessibility +struct MenuFont_t +{ + // int32_t xspace, yline; + vec2_t emptychar, between; + int32_t zoom; + int32_t cursorLeftPosition, cursorCenterPosition, cursorScale; + int32_t textflags; + int16_t tilenum; + // selected shade glows, deselected shade is used by Blood, disabled shade is used by SW + int8_t shade_deselected, shade_disabled; + uint8_t pal; + uint8_t pal_selected, pal_deselected, pal_disabled; + uint8_t pal_selected_right, pal_deselected_right, pal_disabled_right; + + int32_t get_yline() const { return mulscale16(emptychar.y, zoom); } +}; + +extern MenuFont_t MF_Redfont, MF_Bluefont, MF_Minifont; + +void Menu_Init(void); + +inline int G_CheckPlayerColor(int color) +{ + static int32_t player_pals[] = { 0, 9, 10, 11, 12, 13, 14, 15, 16, 21, 23, }; + if (color >= 0 && color < 10) return player_pals[color]; + return 0; +} + + +#if 0 + enum MenuIndex_t { MENU_NULL = INT32_MIN, // sentinel for "do nothing" MENU_CLOSE = -2, // sentinel for "close the menu"/"no menu" MENU_PREVIOUS = -1, // sentinel for "go to previous menu" - MENU_MAIN = 0, - MENU_MAIN_INGAME = 50, - MENU_EPISODE = 100, + MENU_MAIN = 0, // done + MENU_MAIN_INGAME = 50, // done + MENU_EPISODE = 100, // done MENU_USERMAP = 101, - MENU_NEWGAMECUSTOM = 102, - MENU_NEWGAMECUSTOMSUB = 103, - MENU_SKILL = 110, - MENU_GAMESETUP = 200, + MENU_NEWGAMECUSTOM = 102, // done + MENU_NEWGAMECUSTOMSUB = 103,// done + MENU_SKILL = 110, // done MENU_OPTIONS = 202, - MENU_VIDEOSETUP = 203, - MENU_KEYBOARDSETUP = 204, - MENU_MOUSESETUP = 205, - MENU_JOYSTICKSETUP = 206, - MENU_JOYSTICKBTNS = 207, - MENU_JOYSTICKAXES = 208, - MENU_KEYBOARDKEYS = 209, - MENU_MOUSEBTNS = 210, - MENU_MOUSEADVANCED = 212, - MENU_JOYSTICKAXIS = 213, - MENU_TOUCHSETUP = 214, - MENU_TOUCHSENS = 215, - MENU_TOUCHBUTTONS = 216, - MENU_CONTROLS = 220, - MENU_POLYMOST = 230, - MENU_COLCORR = 231, - MENU_COLCORR_INGAME = 232, - MENU_SCREENSETUP = 233, - MENU_DISPLAYSETUP = 234, - MENU_POLYMER = 240, + MENU_GAMESETUP = 200, + MENU_CHEATS = 800, // IF script hacked + MENU_CHEATENTRY = 801, // IF script hacked + MENU_CHEAT_WARP = 802, + MENU_CHEAT_SKILL = 803, + MENU_DISPLAYSETUP = 234, + MENU_SCREENSETUP = 233, // HUD + MENU_COLCORR = 231, // color correction + MENU_COLCORR_INGAME = 232, // almost the same for ingame - not needed + MENU_VIDEOSETUP = 203, + MENU_POLYMOST = 230, + MENU_POLYMER = 240, // Who needs a renderer that's folding performance-wise with a single light? + MENU_SOUND = 700, + MENU_SOUND_INGAME = 701, // Just the same with different exit logic. + MENU_ADVSOUND = 702, // Only needed for space reasons. Fold into main sound menu. + MENU_PLAYER = 20002, + MENU_MACROS = 20004, + MENU_CONTROLS = 220, + MENU_KEYBOARDSETUP = 204, + MENU_KEYBOARDKEYS = 209, + MENU_MOUSESETUP = 205, + MENU_MOUSEBTNS = 210, // folded with keyboard + MENU_MOUSEADVANCED = 212, + MENU_JOYSTICKSETUP = 206, + MENU_JOYSTICKBTNS = 207, + MENU_JOYSTICKAXES = 208, + MENU_JOYSTICKAXIS = 213, MENU_LOAD = 300, MENU_SAVE = 350, MENU_STORY = 400, MENU_F1HELP = 401, + MENU_CREDITS = 990, + MENU_CREDITS2 = 991, + MENU_CREDITS3 = 992, + MENU_CREDITS4 = 993, + MENU_CREDITS5 = 994, MENU_QUIT = 500, MENU_QUITTOTITLE = 501, MENU_QUIT_INGAME = 502, - MENU_NETSETUP = 600, - MENU_NETWAITMASTER = 601, - MENU_NETWAITVOTES = 603, - MENU_SOUND = 700, - MENU_SOUND_INGAME = 701, - MENU_ADVSOUND = 702, + MENU_SAVESETUP = 750, + MENU_SAVECLEANVERIFY = 751, - MENU_CHEATS = 800, - MENU_CHEATENTRY = 801, - MENU_CHEAT_WARP = 802, - MENU_CHEAT_SKILL = 803, - MENU_CREDITS = 990, - MENU_CREDITS2 = 991, - MENU_CREDITS3 = 992, - MENU_CREDITS4 = 993, - MENU_CREDITS5 = 994, MENU_LOADVERIFY = 1000, MENU_LOADDELVERIFY = 1100, MENU_NEWVERIFY = 1500, @@ -98,9 +128,11 @@ enum MenuIndex_t { MENU_ADULTPASSWORD = 10001, MENU_RESETPLAYER = 15000, MENU_BUYDUKE = 20000, + + MENU_NETSETUP = 600, + MENU_NETWAITMASTER = 601, + MENU_NETWAITVOTES = 603, MENU_NETWORK = 20001, - MENU_PLAYER = 20002, - MENU_MACROS = 20004, MENU_NETHOST = 20010, MENU_NETOPTIONS = 20011, MENU_NETUSERMAP = 20012, @@ -108,414 +140,7 @@ enum MenuIndex_t { }; - -typedef int32_t MenuID_t; - - -typedef enum MenuAnimationType_t -{ // Note: This enum is for logical categories, not visual types. - MA_None, - MA_Return, - MA_Advance, -} MenuAnimationType_t; - -// a subset of screentext parameters, restricted because menus require accessibility -typedef struct MenuFont_t -{ -// int32_t xspace, yline; - vec2_t emptychar, between; - int32_t zoom; - int32_t cursorLeftPosition, cursorCenterPosition, cursorScale; - int32_t textflags; - int16_t tilenum; - // selected shade glows, deselected shade is used by Blood, disabled shade is used by SW - int8_t shade_deselected, shade_disabled; - uint8_t pal; - uint8_t pal_selected, pal_deselected, pal_disabled; - uint8_t pal_selected_right, pal_deselected_right, pal_disabled_right; - - int32_t get_yline() const { return mulscale16(emptychar.y, zoom); } -} MenuFont_t; - - - -typedef enum MenuEntryType_t -{ - Dummy, - Link, - Option, - Custom2Col, - RangeInt32, - RangeFloat, -#ifdef MENU_ENABLE_RANGEDOUBLE - RangeDouble, #endif - String, - Spacer, -} MenuEntryType_t; - -typedef struct MenuEntryFormat_t -{ - int32_t marginBottom; - int32_t indent; - int32_t width; // 0: center, >0: width of the label column (left-aligned options), <0: -width of everything (right-aligned) -} MenuEntryFormat_t; - - -typedef struct MenuMenuFormat_t -{ - vec2_t pos; - int32_t bottomcutoff; // >0: the bottom edge of the menu before automatic scrolling kicks in, <0: -total height for vertical justification -} MenuMenuFormat_t; - -typedef struct MenuLink_t -{ - // traits - MenuID_t linkID; - MenuAnimationType_t animation; -} MenuLink_t; -typedef struct MenuOptionSet_t -{ - // traits - char const **optionNames; - int32_t *optionValues; // If NULL, the identity of currentOption is assumed. - - // pop-up list appearance - MenuMenuFormat_t *menuFormat; - MenuEntryFormat_t *entryFormat; - MenuFont_t *font; - - // traits - int32_t numOptions; - - // pop-up list state - int32_t currentEntry; - int32_t scrollPos; - - // appearance - uint8_t features; // bit 1 = disable left/right arrows, bit 2 = disable list - - int32_t getMarginBottom() const { return mulscale16(entryFormat->marginBottom, font->zoom); } - int32_t getIndent() const { return mulscale16(entryFormat->indent, font->zoom); } -} MenuOptionSet_t; -typedef struct MenuOption_t -{ - // appearance - MenuFont_t *font; - - // traits - MenuOptionSet_t *options; // so that common sets such as Yes/No, On/Off can be reused - - // effect - FBaseCVar *cVar; - - // state - int32_t currentOption; -} MenuOption_t; -typedef struct MenuCustom2Col_t -{ - int buttonindex; - - // appearance - MenuFont_t *font; - - // effect - size_t numvalid; - - // appearance - int32_t columnWidth; - - // state - int8_t screenOpen; -} MenuCustom2Col_t; - -enum MenuRangeFlags_t -{ - DisplayTypeInteger = 1, - DisplayTypePercent = 2, - DisplayTypeNormalizedDecimal = 3, - DisplayTypeMask = (1<<0)|(1<<1), - - EnforceIntervals = 1<<7, -}; -typedef struct MenuRangeInt32_t -{ - // effect - FIntCVar *cVar; - - // appearance - MenuFont_t *font; - - // traits - int32_t min; - int32_t max; - int32_t onehundredpercent; // 0 implies max - int32_t steps; - - uint8_t flags; -} MenuRangeInt32_t; -typedef struct MenuRangeFloat_t -{ - // effect - FFloatCVar *cVar; - - // appearance - MenuFont_t *font; - - // traits - float min; - float max; - float onehundredpercent; // 0 implies 1.0 - int32_t steps; - - uint8_t flags; -} MenuRangeFloat_t; -#ifdef MENU_ENABLE_RANGEDOUBLE -typedef struct MenuRangeDouble_t -{ - // effect - double *variable; - - // appearance - MenuFont_t *font; - - // traits - double min; - double max; - double onehundredpercent; // 0 implies 1.0 - int32_t steps; - - uint8_t flags; -} MenuRangeDouble_t; -#endif -typedef struct MenuString_t -{ - // state - char* editfield; - - // effect - char* variable; - - // appearance - MenuFont_t *font; - - // effect - int32_t bufsize; - int32_t flags; -} MenuString_t; -typedef struct MenuSpacer_t -{ - int32_t height; -} MenuSpacer_t; - -// For internal use only. -enum MenuEntryFlags_t -{ - MEF_Disabled = 1<<0, - MEF_LookDisabled = 1<<1, - MEF_Hidden = 1<<2, -}; - -typedef struct MenuEntry_t -{ - // traits - const char *name; - - // appearance - MenuFont_t *font; - MenuEntryFormat_t *format; - - void *entry; - MenuEntryType_t type; - - // state - int32_t flags; - int32_t ytop, ybottom; - - int32_t getMarginBottom() const { return mulscale16(format->marginBottom, font->zoom); } - int32_t getIndent() const { return mulscale16(format->indent, font->zoom); } - int32_t getHeight() const - { - return type == Spacer ? mulscale16(((MenuSpacer_t *)entry)->height, font->zoom) : font->get_yline(); - } -} MenuEntry_t; - - -typedef enum MenuType_t -{ - Menu, - Panel, - Verify, - Message, - TextForm, - FileSelect, -} MenuType_t; - -typedef struct MenuMenu_t -{ - const char *title; - - MenuMenuFormat_t *format; - - MenuEntry_t **entrylist; - int32_t numEntries; - - // state - int32_t currentEntry, currentColumn; - int32_t scrollPos; -} MenuMenu_t; -typedef struct MenuPanel_t -{ - const char *title; - - MenuID_t previousID; - MenuAnimationType_t previousAnimation; - MenuID_t nextID; - MenuAnimationType_t nextAnimation; -} MenuPanel_t; -typedef struct MenuVerify_t -{ - vec2_t cursorpos; - - MenuID_t linkID; - MenuAnimationType_t animation; -} MenuVerify_t; -typedef struct MenuMessage_t -{ - vec2_t cursorpos; - - MenuID_t linkID; - MenuAnimationType_t animation; -} MenuMessage_t; -enum MenuTextFormFlags_t -{ - MTF_Password = 1<<0, -}; -typedef struct MenuTextForm_t -{ - // state - char *input; - - // traits - const char *instructions; - int32_t bufsize; - uint8_t flags; -} MenuTextForm_t; -typedef struct MenuFileSelect_t -{ - const char *title; - - // appearance - MenuMenuFormat_t *format[2]; - MenuFont_t *font[2]; - - // traits - const char * startdir; - const char *pattern; - char *destination; - - // state - //CACHE1D_FIND_REC *findhigh[2]; - int32_t scrollPos[2]; - - // appearance - int32_t marginBottom[2]; - - // state - //fnlist_t fnlist; - int32_t currentList; - - int32_t getMarginBottom(size_t index) const { return mulscale16(marginBottom[index], font[index]->zoom); } -} MenuFileSelect_t; - -typedef struct Menu_t -{ - void *object; - MenuID_t menuID; - MenuID_t parentID; - MenuAnimationType_t parentAnimation; - MenuType_t type; -} Menu_t; - -typedef struct MenuAnimation_t -{ - int32_t(*out)(struct MenuAnimation_t *); - int32_t(*in)(struct MenuAnimation_t *); - - Menu_t *previous; - Menu_t *current; - - int32_t start; - int32_t length; -} MenuAnimation_t; - -extern MenuAnimation_t m_animation; - -extern MenuID_t g_currentMenu; -extern Menu_t *m_currentMenu; - -extern int32_t g_quitDeadline; -extern int32_t voting; -int Menu_Change(MenuID_t cm); -void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype); -int32_t Menu_IsTextInput(Menu_t *cm); -int G_CheckPlayerColor(int color); -void Menu_Init(void); -void Menu_Open(uint8_t playerID); -void Menu_Close(uint8_t playerID); -void M_DisplayMenus(void); - -extern MenuFont_t MF_Redfont, MF_Bluefont, MF_Minifont; - -#define M_MOUSETIMEOUT 210 -extern int32_t m_mouselastactivity; - -#if defined EDUKE32_TOUCH_DEVICES -# define MOUSEALPHA 0 -# define CURSORALPHA (255/3) -# define MOUSEACTIVECONDITIONAL(condition) (condition) -# define MOUSEWATCHPOINTCONDITIONAL(condition) (condition) -#else -extern int32_t m_mousewake_watchpoint, m_menuchange_watchpoint; -// alpha increments of 3 --> 255 / 3 = 85 --> round up to power of 2 --> 128 --> divide by 2 --> 64 alphatabs required -// use 16 anyway :P -# define MOUSEUSEALPHA (videoGetRenderMode() != REND_CLASSIC || numalphatabs >= 15) -# define MOUSEALPHA (MOUSEUSEALPHA ? clamp(((int32_t) totalclock - m_mouselastactivity - 90)*3, 0, 255) : 0) -# define CURSORALPHA (MOUSEUSEALPHA ? clamp(((int32_t) totalclock - m_mouselastactivity - 90)*2 + (255/3), (255/3), 255) : 255/3) -# define MOUSEACTIVECONDITION (totalclock - m_mouselastactivity < M_MOUSETIMEOUT) -# define MOUSEACTIVECONDITIONAL(condition) (MOUSEACTIVECONDITION && (condition)) -# define MOUSEINACTIVECONDITIONAL(condition) ((!(g_player[myconnectindex].ps->gm & MODE_MENU) || !MOUSEACTIVECONDITION) && (condition)) -# define MOUSEWATCHPOINTCONDITIONAL(condition) ((condition) || m_mousewake_watchpoint || m_menuchange_watchpoint == 3) -#endif - - -#define MAXMENUGAMEPLAYENTRIES 7 - -enum MenuGameplayEntryFlags -{ - MGE_Locked = 1u<<0u, - MGE_Hidden = 1u<<1u, - MGE_UserContent = 1u<<2u, -}; - -typedef struct MenuGameplayEntry -{ - char name[64]; - uint8_t flags; - - bool isValid() const { return name[0] != '\0'; } -} MenuGameplayEntry; - -typedef struct MenuGameplayStemEntry -{ - MenuGameplayEntry entry; - MenuGameplayEntry subentries[MAXMENUGAMEPLAYENTRIES]; -} MenuGameplayStemEntry; - -extern MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES]; - -extern MenuEntry_t ME_NEWGAMECUSTOMENTRIES[MAXMENUGAMEPLAYENTRIES]; -extern MenuEntry_t ME_NEWGAMECUSTOMSUBENTRIES[MAXMENUGAMEPLAYENTRIES][MAXMENUGAMEPLAYENTRIES]; END_DUKE_NS diff --git a/source/duke3d/src/names.h b/source/duke3d/src/names.h deleted file mode 100644 index 5e1fffec5..000000000 --- a/source/duke3d/src/names.h +++ /dev/null @@ -1,764 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2010 EDuke32 developers and contributors - -This file is part of EDuke32. - -EDuke32 is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- - -#define SECTOREFFECTOR 1 -#define ACTIVATOR 2 -#define TOUCHPLATE 3 -#define ACTIVATORLOCKED 4 -#define MUSICANDSFX 5 -#define LOCATORS 6 -#define CYCLER 7 -#define MASTERSWITCH 8 -#define RESPAWN 9 -#define GPSPEED 10 -#define FOF 13 -#define ARROW 20 -#define FIRSTGUNSPRITE 21 -#define CHAINGUNSPRITE 22 -#define RPGSPRITE 23 -#define FREEZESPRITE 24 -#define SHRINKERSPRITE 25 -#define HEAVYHBOMB 26 -#define TRIPBOMBSPRITE 27 -#define SHOTGUNSPRITE 28 -#define DEVISTATORSPRITE 29 -#define HEALTHBOX 30 -#define AMMOBOX 31 -#define GROWSPRITEICON 32 -#define INVENTORYBOX 33 -#define FREEZEAMMO 37 -#define AMMO 40 -#define BATTERYAMMO 41 -#define DEVISTATORAMMO 42 -#define RPGAMMO 44 -#define GROWAMMO 45 -#define CRYSTALAMMO 46 -#define HBOMBAMMO 47 -#define AMMOLOTS 48 -#define SHOTGUNAMMO 49 -#define COLA 51 -#define SIXPAK 52 -#define FIRSTAID 53 -#define SHIELD 54 -#define STEROIDS 55 -#define AIRTANK 56 -#define JETPACK 57 -#define HEATSENSOR 59 -#define ACCESSCARD 60 -#define BOOTS 61 -#define MIRRORBROKE 70 -#define CLOUDYOCEAN 78 -#define CLOUDYSKIES 79 -#define MOONSKY1 80 -#define MOONSKY2 81 -#define MOONSKY3 82 -#define MOONSKY4 83 -#define BIGORBIT1 84 -#define BIGORBIT2 85 -#define BIGORBIT3 86 -#define BIGORBIT4 87 -#define BIGORBIT5 88 -#define LA 89 -#define REDSKY1 98 -#define REDSKY2 99 -#define ATOMICHEALTH 100 -#define TECHLIGHT2 120 -#define TECHLIGHTBUST2 121 -#define TECHLIGHT4 122 -#define TECHLIGHTBUST4 123 -#define WALLLIGHT4 124 -#define WALLLIGHTBUST4 125 -#define ACCESSSWITCH 130 -#define SLOTDOOR 132 -#define LIGHTSWITCH 134 -#define SPACEDOORSWITCH 136 -#define SPACELIGHTSWITCH 138 -#define FRANKENSTINESWITCH 140 -#define NUKEBUTTON 142 -#define MULTISWITCH 146 -#define DOORTILE5 150 -#define DOORTILE6 151 -#define DOORTILE1 152 -#define DOORTILE2 153 -#define DOORTILE3 154 -#define DOORTILE4 155 -#define DOORTILE7 156 -#define DOORTILE8 157 -#define DOORTILE9 158 -#define DOORTILE10 159 -#define DOORSHOCK 160 -#define DIPSWITCH 162 -#define DIPSWITCH2 164 -#define TECHSWITCH 166 -#define DIPSWITCH3 168 -#define ACCESSSWITCH2 170 -#define REFLECTWATERTILE 180 -#define FLOORSLIME 200 -#define BIGFORCE 230 -#define EPISODE 247 -#define MASKWALL9 255 -#define W_LIGHT 260 -#define SCREENBREAK1 263 -#define SCREENBREAK2 264 -#define SCREENBREAK3 265 -#define SCREENBREAK4 266 -#define SCREENBREAK5 267 -#define SCREENBREAK6 268 -#define SCREENBREAK7 269 -#define SCREENBREAK8 270 -#define SCREENBREAK9 271 -#define SCREENBREAK10 272 -#define SCREENBREAK11 273 -#define SCREENBREAK12 274 -#define SCREENBREAK13 275 -#define MASKWALL1 285 -#define W_TECHWALL1 293 -#define W_TECHWALL2 297 -#define W_TECHWALL15 299 -#define W_TECHWALL3 301 -#define W_TECHWALL4 305 -#define W_TECHWALL10 306 -#define W_TECHWALL16 307 -#define WATERTILE2 336 -#define BPANNEL1 341 -#define PANNEL1 342 -#define PANNEL2 343 -#define WATERTILE 344 -#define STATIC 351 -#define W_SCREENBREAK 357 -#define W_HITTECHWALL3 360 -#define W_HITTECHWALL4 361 -#define W_HITTECHWALL2 362 -#define W_HITTECHWALL1 363 -#define MASKWALL10 387 -#define MASKWALL11 391 -#define DOORTILE22 395 -#define FANSPRITE 407 -#define FANSPRITEBROKE 411 -#define FANSHADOW 412 -#define FANSHADOWBROKE 416 -#define DOORTILE18 447 -#define DOORTILE19 448 -#define DOORTILE20 449 -#define SPACESHUTTLE 487 -#define SATELLITE 489 -#define VIEWSCREEN2 499 -#define VIEWSCREENBROKE 501 -#define VIEWSCREEN 502 -#define GLASS 503 -#define GLASS2 504 -#define STAINGLASS1 510 -#define MASKWALL5 514 -#define SATELITE 516 -#define FUELPOD 517 -#define SLIMEPIPE 538 -#define CRACK1 546 -#define CRACK2 547 -#define CRACK3 548 -#define CRACK4 549 -#define FOOTPRINTS 550 -#define DOMELITE 551 -#define CAMERAPOLE 554 -#define CHAIR1 556 -#define CHAIR2 557 -#define BROKENCHAIR 559 -#define MIRROR 560 -#define WATERFOUNTAIN 563 -#define WATERFOUNTAINBROKE 567 -#define FEMMAG1 568 -#define TOILET 569 -#define STALL 571 -#define STALLBROKE 573 -#define FEMMAG2 577 -#define REACTOR2 578 -#define REACTOR2BURNT 579 -#define REACTOR2SPARK 580 -#define GRATE1 595 -#define BGRATE1 596 -#define SOLARPANNEL 602 -#define NAKED1 603 -#define ANTENNA 607 -#define MASKWALL12 609 -#define TOILETBROKE 615 -#define PIPE2 616 -#define PIPE1B 617 -#define PIPE3 618 -#define PIPE1 619 -#define CAMERA1 621 -#define BRICK 626 -#define SPLINTERWOOD 630 -#define PIPE2B 633 -#define BOLT1 634 -#define W_NUMBERS 640 -#define WATERDRIP 660 -#define WATERBUBBLE 661 -#define WATERBUBBLEMAKER 662 -#define W_FORCEFIELD 663 -#define VACUUM 669 -#define FOOTPRINTS2 672 -#define FOOTPRINTS3 673 -#define FOOTPRINTS4 674 -#define EGG 675 -#define SCALE 678 -#define CHAIR3 680 -#define CAMERALIGHT 685 -#define MOVIECAMERA 686 -#define IVUNIT 689 -#define POT1 694 -#define POT2 695 -#define POT3 697 -#define PIPE3B 700 -#define WALLLIGHT3 701 -#define WALLLIGHTBUST3 702 -#define WALLLIGHT1 703 -#define WALLLIGHTBUST1 704 -#define WALLLIGHT2 705 -#define WALLLIGHTBUST2 706 -#define LIGHTSWITCH2 712 -#define WAITTOBESEATED 716 -#define DOORTILE14 717 -#define STATUE 753 -#define MIKE 762 -#define VASE 765 -#define SUSHIPLATE1 768 -#define SUSHIPLATE2 769 -#define SUSHIPLATE3 774 -#define SUSHIPLATE4 779 -#define DOORTILE16 781 -#define SUSHIPLATE5 792 -#define OJ 806 -#define MASKWALL13 830 -#define HURTRAIL 859 -#define POWERSWITCH1 860 -#define LOCKSWITCH1 862 -#define POWERSWITCH2 864 -#define ATM 867 -#define STATUEFLASH 869 -#define ATMBROKE 888 -#define BIGHOLE2 893 -#define STRIPEBALL 901 -#define QUEBALL 902 -#define POCKET 903 -#define WOODENHORSE 904 -#define TREE1 908 -#define TREE2 910 -#define CACTUS 911 -#define MASKWALL2 913 -#define MASKWALL3 914 -#define MASKWALL4 915 -#define FIREEXT 916 -#define TOILETWATER 921 -#define NEON1 925 -#define NEON2 926 -#define CACTUSBROKE 939 -#define BOUNCEMINE 940 -#define BROKEFIREHYDRENT 950 -#define BOX 951 -#define BULLETHOLE 952 -#define BOTTLE1 954 -#define BOTTLE2 955 -#define BOTTLE3 956 -#define BOTTLE4 957 -#define FEMPIC5 963 -#define FEMPIC6 964 -#define FEMPIC7 965 -#define HYDROPLANT 969 -#define OCEANSPRITE1 971 -#define OCEANSPRITE2 972 -#define OCEANSPRITE3 973 -#define OCEANSPRITE4 974 -#define OCEANSPRITE5 975 -#define GENERICPOLE 977 -#define CONE 978 -#define HANGLIGHT 979 -#define HYDRENT 981 -#define MASKWALL14 988 -#define TIRE 990 -#define PIPE5 994 -#define PIPE6 995 -#define PIPE4 996 -#define PIPE4B 997 -#define BROKEHYDROPLANT 1003 -#define PIPE5B 1005 -#define NEON3 1007 -#define NEON4 1008 -#define NEON5 1009 -#define BOTTLE5 1012 -#define BOTTLE6 1013 -#define BOTTLE8 1014 -#define SPOTLITE 1020 -#define HANGOOZ 1022 -#define MASKWALL15 1024 -#define BOTTLE7 1025 -#define HORSEONSIDE 1026 -#define GLASSPIECES 1031 -#define HORSELITE 1034 -#define DONUTS 1045 -#define NEON6 1046 -#define MASKWALL6 1059 -#define CLOCK 1060 -#define RUBBERCAN 1062 -#define BROKENCLOCK 1067 -#define PLUG 1069 -#define OOZFILTER 1079 -#define FLOORPLASMA 1082 -#define REACTOR 1088 -#define REACTORSPARK 1092 -#define REACTORBURNT 1096 -#define DOORTILE15 1102 -#define HANDSWITCH 1111 -#define CIRCLEPANNEL 1113 -#define CIRCLEPANNELBROKE 1114 -#define PULLSWITCH 1122 -#define MASKWALL8 1124 -#define BIGHOLE 1141 -#define ALIENSWITCH 1142 -#define DOORTILE21 1144 -#define HANDPRINTSWITCH 1155 -#define BOTTLE10 1157 -#define BOTTLE11 1158 -#define BOTTLE12 1159 -#define BOTTLE13 1160 -#define BOTTLE14 1161 -#define BOTTLE15 1162 -#define BOTTLE16 1163 -#define BOTTLE17 1164 -#define BOTTLE18 1165 -#define BOTTLE19 1166 -#define DOORTILE17 1169 -#define MASKWALL7 1174 -#define JAILBARBREAK 1175 -#define DOORTILE11 1178 -#define DOORTILE12 1179 -#define VENDMACHINE 1212 -#define VENDMACHINEBROKE 1214 -#define COLAMACHINE 1215 -#define COLAMACHINEBROKE 1217 -#define CRANEPOLE 1221 -#define CRANE 1222 -#define BARBROKE 1225 -#define BLOODPOOL 1226 -#define NUKEBARREL 1227 -#define NUKEBARRELDENTED 1228 -#define NUKEBARRELLEAKED 1229 -#define CANWITHSOMETHING 1232 -#define MONEY 1233 -#define BANNER 1236 -#define EXPLODINGBARREL 1238 -#define EXPLODINGBARREL2 1239 -#define FIREBARREL 1240 -#define SEENINE 1247 -#define SEENINEDEAD 1248 -#define STEAM 1250 -#define CEILINGSTEAM 1255 -#define PIPE6B 1260 -#define TRANSPORTERBEAM 1261 -#define RAT 1267 -#define TRASH 1272 -#define FEMPIC1 1280 -#define FEMPIC2 1289 -#define BLANKSCREEN 1293 -#define PODFEM1 1294 -#define FEMPIC3 1298 -#define FEMPIC4 1306 -#define FEM1 1312 -#define FEM2 1317 -#define FEM3 1321 -#define FEM5 1323 -#define BLOODYPOLE 1324 -#define FEM4 1325 -#define FEM6 1334 -#define FEM6PAD 1335 -#define FEM8 1336 -#define HELECOPT 1346 -#define FETUSJIB 1347 -#define HOLODUKE 1348 -#define SPACEMARINE 1353 -#define INDY 1355 -#define FETUS 1358 -#define FETUSBROKE 1359 -#define MONK 1352 -#define LUKE 1354 -#define COOLEXPLOSION1 1360 -#define WATERSPLASH2 1380 -#define FIREVASE 1390 -#define SCRATCH 1393 -#define FEM7 1395 -#define APLAYERTOP 1400 -#define APLAYER 1405 -#define PLAYERONWATER 1420 -#define DUKELYINGDEAD 1518 -#define DUKETORSO 1520 -#define DUKEGUN 1528 -#define DUKELEG 1536 -#define SHARK 1550 -#define BLOOD 1620 -#define FIRELASER 1625 -#define TRANSPORTERSTAR 1630 -#define SPIT 1636 -#define LOOGIE 1637 -#define FIST 1640 -#define FREEZEBLAST 1641 -#define DEVISTATORBLAST 1642 -#define SHRINKSPARK 1646 -#define TONGUE 1647 -#define MORTER 1650 -#define SHRINKEREXPLOSION 1656 -#define RADIUSEXPLOSION 1670 -#define FORCERIPPLE 1671 -#define LIZTROOP 1680 -#define LIZTROOPRUNNING 1681 -#define LIZTROOPSTAYPUT 1682 -#define LIZTOP 1705 -#define LIZTROOPSHOOT 1715 -#define LIZTROOPJETPACK 1725 -#define LIZTROOPDSPRITE 1734 -#define LIZTROOPONTOILET 1741 -#define LIZTROOPJUSTSIT 1742 -#define LIZTROOPDUCKING 1744 -#define HEADJIB1 1768 -#define ARMJIB1 1772 -#define LEGJIB1 1776 -#define CANNON 1810 -#define CANNONBALL 1817 -#define CANNONBALLS 1818 -#define OCTABRAIN 1820 -#define OCTABRAINSTAYPUT 1821 -#define OCTATOP 1845 -#define OCTADEADSPRITE 1855 -#define INNERJAW 1860 -#define DRONE 1880 -#define EXPLOSION2 1890 -#define COMMANDER 1920 -#define COMMANDERSTAYPUT 1921 -#define RECON 1960 -#define TANK 1975 -#define PIGCOP 2000 -#define PIGCOPSTAYPUT 2001 -#define PIGCOPDIVE 2045 -#define PIGCOPDEADSPRITE 2060 -#define PIGTOP 2061 -#define LIZMAN 2120 -#define LIZMANSTAYPUT 2121 -#define LIZMANSPITTING 2150 -#define LIZMANFEEDING 2160 -#define LIZMANJUMP 2165 -#define LIZMANDEADSPRITE 2185 -#define FECES 2200 -#define LIZMANHEAD1 2201 -#define LIZMANARM1 2205 -#define LIZMANLEG1 2209 -#define EXPLOSION2BOT 2219 -#define USERWEAPON 2235 -#define HEADERBAR 2242 -#define JIBS1 2245 -#define JIBS2 2250 -#define JIBS3 2255 -#define JIBS4 2260 -#define JIBS5 2265 -#define BURNING 2270 -#define FIRE 2271 -#define JIBS6 2286 -#define BLOODSPLAT1 2296 -#define BLOODSPLAT3 2297 -#define BLOODSPLAT2 2298 -#define BLOODSPLAT4 2299 -#define OOZ 2300 -#define OOZ2 2309 -#define WALLBLOOD1 2301 -#define WALLBLOOD2 2302 -#define WALLBLOOD3 2303 -#define WALLBLOOD4 2304 -#define WALLBLOOD5 2305 -#define WALLBLOOD6 2306 -#define WALLBLOOD7 2307 -#define WALLBLOOD8 2308 -#define BURNING2 2310 -#define FIRE2 2311 -#define CRACKKNUCKLES 2324 -#define SMALLSMOKE 2329 -#define SMALLSMOKEMAKER 2330 -#define FLOORFLAME 2333 -#define ROTATEGUN 2360 -#define GREENSLIME 2370 -#define WATERDRIPSPLASH 2380 -#define SCRAP6 2390 -#define SCRAP1 2400 -#define SCRAP2 2404 -#define SCRAP3 2408 -#define SCRAP4 2412 -#define SCRAP5 2416 -#define ORGANTIC 2420 -#define BETAVERSION 2440 -#define PLAYERISHERE 2442 -#define PLAYERWASHERE 2443 -#define SELECTDIR 2444 -#define F1HELP 2445 -#define NOTCHON 2446 -#define NOTCHOFF 2447 -#define GROWSPARK 2448 -#define DUKEICON 2452 -#define BADGUYICON 2453 -#define FOODICON 2454 -#define GETICON 2455 -#define MENUSCREEN 2456 -#define MENUBAR 2457 -#define KILLSICON 2458 -#define FIRSTAID_ICON 2460 -#define HEAT_ICON 2461 -#define BOTTOMSTATUSBAR 2462 -#define BOOT_ICON 2463 -#define FRAGBAR 2465 -#define JETPACK_ICON 2467 -#define AIRTANK_ICON 2468 -#define STEROIDS_ICON 2469 -#define HOLODUKE_ICON 2470 -#define ACCESS_ICON 2471 -#define DIGITALNUM 2472 -#define DUKECAR 2491 -#define CAMCORNER 2482 -#define CAMLIGHT 2484 -#define LOGO 2485 -#define TITLE 2486 -#define NUKEWARNINGICON 2487 -#define MOUSECURSOR 2488 -#define SLIDEBAR 2489 -#define DREALMS 2492 -#define BETASCREEN 2493 -#define WINDOWBORDER1 2494 -#define TEXTBOX 2495 -#define WINDOWBORDER2 2496 -#define DUKENUKEM 2497 -#define THREEDEE 2498 -#define INGAMEDUKETHREEDEE 2499 -#define TENSCREEN 2500 -#define PLUTOPAKSPRITE 2501 -#define DEVISTATOR 2510 -#define KNEE 2521 -#define CROSSHAIR 2523 -#define FIRSTGUN 2524 -#define FIRSTGUNRELOAD 2528 -#define FALLINGCLIP 2530 -#define CLIPINHAND 2531 -#define HAND 2532 -#define SHELL 2533 -#define SHOTGUNSHELL 2535 -#define CHAINGUN 2536 -#define RPGGUN 2544 -#define RPGMUZZLEFLASH 2545 -#define FREEZE 2548 -#define CATLITE 2552 -#define SHRINKER 2556 -#define HANDHOLDINGLASER 2563 -#define TRIPBOMB 2566 -#define LASERLINE 2567 -#define HANDHOLDINGACCESS 2568 -#define HANDREMOTE 2570 -#define HANDTHROW 2573 -#define TIP 2576 -#define GLAIR 2578 -#define SCUBAMASK 2581 -#define SPACEMASK 2584 -#define FORCESPHERE 2590 -#define SHOTSPARK1 2595 -#define RPG 2605 -#define LASERSITE 2612 -#define SHOTGUN 2613 -#define BOSS1 2630 -#define BOSS1STAYPUT 2631 -#define BOSS1SHOOT 2660 -#define BOSS1LOB 2670 -#define BOSSTOP 2696 -#define BOSS2 2710 -#define BOSS3 2760 -#define SPINNINGNUKEICON 2813 -#define BIGFNTCURSOR 2820 -#define SMALLFNTCURSOR 2821 -#define STARTALPHANUM 2822 -#define ENDALPHANUM 2915 -#define BIGALPHANUM 2940 -#define BIGPERIOD 3002 -#define BIGCOMMA 3003 -#define BIGX 3004 -#define BIGQ 3005 -#define BIGSEMI 3006 -#define BIGCOLIN 3007 -#define THREEBYFIVE 3010 -#define BIGAPPOS 3022 -#define BLANK 3026 -#define MINIFONT 3072 -#define BUTTON1 3164 -#define GLASS3 3187 -#define RESPAWNMARKERRED 3190 -#define RESPAWNMARKERYELLOW 3200 -#define RESPAWNMARKERGREEN 3210 -#define BONUSSCREEN 3240 -#define VIEWBORDER 3250 -#define VICTORY1 3260 -#define ORDERING 3270 -#define TEXTSTORY 3280 -#define LOADSCREEN 3281 -#define BORNTOBEWILDSCREEN 3370 -#define BLIMP 3400 -#define FEM9 3450 -#define FOOTPRINT 3701 -#define FRAMEEFFECT1_13 3999 -#define POOP 4094 -#define FRAMEEFFECT1 4095 -#define PANNEL3 4099 -#define SCREENBREAK14 4120 -#define SCREENBREAK15 4123 -#define SCREENBREAK19 4125 -#define SCREENBREAK16 4127 -#define SCREENBREAK17 4128 -#define SCREENBREAK18 4129 -#define W_TECHWALL11 4130 -#define W_TECHWALL12 4131 -#define W_TECHWALL13 4132 -#define W_TECHWALL14 4133 -#define W_TECHWALL5 4134 -#define W_TECHWALL6 4136 -#define W_TECHWALL7 4138 -#define W_TECHWALL8 4140 -#define W_TECHWALL9 4142 -#define BPANNEL3 4100 -#define W_HITTECHWALL16 4144 -#define W_HITTECHWALL10 4145 -#define W_HITTECHWALL15 4147 -#define W_MILKSHELF 4181 -#define W_MILKSHELFBROKE 4203 -#define PURPLELAVA 4240 -#define LAVABUBBLE 4340 -#define DUKECUTOUT 4352 -#define TARGET 4359 -#define GUNPOWDERBARREL 4360 -#define DUCK 4361 -#define HATRACK 4367 -#define DESKLAMP 4370 -#define COFFEEMACHINE 4372 -#define CUPS 4373 -#define GAVALS 4374 -#define GAVALS2 4375 -#define POLICELIGHTPOLE 4377 -#define FLOORBASKET 4388 -#define PUKE 4389 -#define DOORTILE23 4391 -#define TOPSECRET 4396 -#define SPEAKER 4397 -#define TEDDYBEAR 4400 -#define ROBOTDOG 4402 -#define ROBOTPIRATE 4404 -#define ROBOTMOUSE 4407 -#define MAIL 4410 -#define MAILBAG 4413 -#define HOTMEAT 4427 -#define COFFEEMUG 4438 -#define DONUTS2 4440 -#define TRIPODCAMERA 4444 -#define METER 4453 -#define DESKPHONE 4454 -#define GUMBALLMACHINE 4458 -#define GUMBALLMACHINEBROKE 4459 -#define PAPER 4460 -#define MACE 4464 -#define GENERICPOLE2 4465 -#define XXXSTACY 4470 -#define WETFLOOR 4495 -#define BROOM 4496 -#define MOP 4497 -#define LETTER 4502 -#define PIRATE1A 4510 -#define PIRATE4A 4511 -#define PIRATE2A 4512 -#define PIRATE5A 4513 -#define PIRATE3A 4514 -#define PIRATE6A 4515 -#define PIRATEHALF 4516 -#define CHESTOFGOLD 4520 -#define SIDEBOLT1 4525 -#define FOODOBJECT1 4530 -#define FOODOBJECT2 4531 -#define FOODOBJECT3 4532 -#define FOODOBJECT4 4533 -#define FOODOBJECT5 4534 -#define FOODOBJECT6 4535 -#define FOODOBJECT7 4536 -#define FOODOBJECT8 4537 -#define FOODOBJECT9 4538 -#define FOODOBJECT10 4539 -#define FOODOBJECT11 4540 -#define FOODOBJECT12 4541 -#define FOODOBJECT13 4542 -#define FOODOBJECT14 4543 -#define FOODOBJECT15 4544 -#define FOODOBJECT16 4545 -#define FOODOBJECT17 4546 -#define FOODOBJECT18 4547 -#define FOODOBJECT19 4548 -#define FOODOBJECT20 4549 -#define HEADLAMP 4550 -#define TAMPON 4557 -#define SKINNEDCHICKEN 4554 -#define FEATHEREDCHICKEN 4555 -#define ROBOTDOG2 4560 -#define JOLLYMEAL 4569 -#define DUKEBURGER 4570 -#define SHOPPINGCART 4576 -#define CANWITHSOMETHING2 4580 -#define CANWITHSOMETHING3 4581 -#define CANWITHSOMETHING4 4582 -#define SNAKEP 4590 -#define DOLPHIN1 4591 -#define DOLPHIN2 4592 -#define NEWBEAST 4610 -#define NEWBEASTSTAYPUT 4611 -#define NEWBEASTJUMP 4690 -#define NEWBEASTHANG 4670 -#define NEWBEASTHANGDEAD 4671 -#define BOSS4 4740 -#define BOSS4STAYPUT 4741 -#define FEM10 4864 -#define TOUGHGAL 4866 -#define MAN 4871 -#define MAN2 4872 -#define WOMAN 4874 -#define PLEASEWAIT 4887 -#define NATURALLIGHTNING 4890 -#define WEATHERWARN 4893 -#define DUKETAG 4900 -#define SIGN1 4909 -#define SIGN2 4912 -#define JURYGUY 4943 - -// These tile positions are reserved! -#define RESERVEDSLOT1 6132 -#define RESERVEDSLOT2 6133 -#define RESERVEDSLOT3 6134 -#define RESERVEDSLOT4 6135 -#define RESERVEDSLOT5 6136 -#define RESERVEDSLOT6 6137 -#define RESERVEDSLOT7 6138 -#define RESERVEDSLOT8 6139 -#define RESERVEDSLOT9 6140 -#define RESERVEDSLOT10 6141 -#define RESERVEDSLOT11 6142 -#define RESERVEDSLOT12 6143 diff --git a/source/duke3d/src/namesdyn.cpp b/source/duke3d/src/namesdyn.cpp index ac381ca07..d4b8fb520 100644 --- a/source/duke3d/src/namesdyn.cpp +++ b/source/duke3d/src/namesdyn.cpp @@ -27,14 +27,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "namesdyn.h" #include "global.h" +#include "gamecontrol.h" BEGIN_DUKE_NS -#ifdef DYNTILEREMAP_ENABLE # define DVPTR(x) &x -#else -# define DVPTR(x) NULL -#endif int16_t DynamicTileMap[MAXTILES]; @@ -170,6 +167,9 @@ LUNATIC_EXTERN struct dynitem g_dynTileList[] = { "CRACKKNUCKLES", DVPTR(CRACKKNUCKLES), CRACKKNUCKLES__STATIC }, { "CRANE", DVPTR(CRANE), CRANE__STATIC }, { "CRANEPOLE", DVPTR(CRANEPOLE), CRANEPOLE__STATIC }, + { "CREDITSTEXT1", DVPTR(CREDITSTEXT1), CREDITSTEXT1__STATIC }, + { "CREDITSTEXT2", DVPTR(CREDITSTEXT2), CREDITSTEXT2__STATIC }, + { "CREDITSTEXT3", DVPTR(CREDITSTEXT3), CREDITSTEXT3__STATIC }, { "CROSSHAIR", DVPTR(CROSSHAIR), CROSSHAIR__STATIC }, { "CRYSTALAMMO", DVPTR(CRYSTALAMMO), CRYSTALAMMO__STATIC }, { "CYCLER", DVPTR(CYCLER), CYCLER__STATIC }, @@ -642,7 +642,7 @@ LUNATIC_EXTERN struct dynitem g_dynTileList[] = { "XXXSTACY", DVPTR(XXXSTACY), XXXSTACY__STATIC }, }; -#ifdef DYNTILEREMAP_ENABLE + int32_t ACCESS_ICON = ACCESS_ICON__STATIC; int32_t ACCESSCARD = ACCESSCARD__STATIC; int32_t ACCESSSWITCH = ACCESSSWITCH__STATIC; @@ -766,6 +766,9 @@ int32_t CRACK4 = CRACK4__STATIC; int32_t CRACKKNUCKLES = CRACKKNUCKLES__STATIC; int32_t CRANE = CRANE__STATIC; int32_t CRANEPOLE = CRANEPOLE__STATIC; +int32_t CREDITSTEXT1 = CREDITSTEXT1__STATIC; +int32_t CREDITSTEXT2 = CREDITSTEXT2__STATIC; +int32_t CREDITSTEXT3 = CREDITSTEXT3__STATIC; int32_t CROSSHAIR = CROSSHAIR__STATIC; int32_t CRYSTALAMMO = CRYSTALAMMO__STATIC; int32_t CYCLER = CYCLER__STATIC; @@ -1237,7 +1240,6 @@ int32_t WOMAN = WOMAN__STATIC; int32_t WOODENHORSE = WOODENHORSE__STATIC; int32_t XXXSTACY = XXXSTACY__STATIC; -#if !defined LUNATIC static hashtable_t h_names = {512, NULL}; void G_ProcessDynamicTileMapping(const char *szLabel, int32_t lValue) @@ -1250,10 +1252,6 @@ void G_ProcessDynamicTileMapping(const char *szLabel, int32_t lValue) if (i>=0) { struct dynitem *di = &g_dynTileList[i]; -#ifdef DEBUGGINGAIDS - if (g_scriptDebug && di->staticval != lValue) - OSD_Printf("REMAP %s (%d) --> %d\n", di->str, di->staticval, lValue); -#endif *di->dynvalptr = lValue; } } @@ -1270,8 +1268,6 @@ void freehashnames(void) { hash_free(&h_names); } -#endif -#endif // This is run after all CON define's have been processed to set up the // dynamic->static tile mapping. @@ -1280,11 +1276,10 @@ void G_InitDynamicTiles(void) Bmemset(DynamicTileMap, 0, sizeof(DynamicTileMap)); for (auto & i : g_dynTileList) -#ifdef DYNTILEREMAP_ENABLE + { DynamicTileMap[*(i.dynvalptr)] = i.staticval; -#else - DynamicTileMap[i.staticval] = i.staticval; -#endif + NameToTileIndex.Insert(i.str, *(i.dynvalptr)); + } g_blimpSpawnItems[0] = RPGSPRITE; g_blimpSpawnItems[1] = CHAINGUNSPRITE; @@ -1314,10 +1309,5 @@ void G_InitDynamicTiles(void) WeaponPickupSprites[9] = FREEZESPRITE; WeaponPickupSprites[10] = HEAVYHBOMB; WeaponPickupSprites[11] = SHRINKERSPRITE; - - // ouch... the big background image takes up a fuckload of memory and takes a second to load! -#ifdef EDUKE32_GLES - MENUSCREEN = LOADSCREEN = BETASCREEN; -#endif } END_DUKE_NS diff --git a/source/duke3d/src/namesdyn.h b/source/duke3d/src/namesdyn.h index c87b2e06a..6b5dcfe24 100644 --- a/source/duke3d/src/namesdyn.h +++ b/source/duke3d/src/namesdyn.h @@ -26,9 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_DUKE_NS -#define DYNTILEREMAP_ENABLE - - #define SECTOREFFECTOR__STATIC 1 #define ACTIVATOR__STATIC 2 #define TOUCHPLATE__STATIC 3 @@ -505,6 +502,9 @@ BEGIN_DUKE_NS #define INGAMEDUKETHREEDEE__STATIC 2499 #define TENSCREEN__STATIC 2500 #define PLUTOPAKSPRITE__STATIC 2501 +#define CREDITSTEXT1__STATIC 2504 +#define CREDITSTEXT2__STATIC 2505 +#define CREDITSTEXT3__STATIC 2506 #define DEVISTATOR__STATIC 2510 #define KNEE__STATIC 2521 #define CROSSHAIR__STATIC 2523 @@ -627,8 +627,6 @@ extern int16_t DynamicTileMap[MAXTILES]; void G_InitDynamicTiles(void); -#ifdef DYNTILEREMAP_ENABLE - void G_ProcessDynamicTileMapping(const char *szLabel, int32_t lValue); #if !defined LUNATIC @@ -759,6 +757,9 @@ extern int32_t CRACK4; extern int32_t CRACKKNUCKLES; extern int32_t CRANE; extern int32_t CRANEPOLE; +extern int32_t CREDITSTEXT1; +extern int32_t CREDITSTEXT2; +extern int32_t CREDITSTEXT3; extern int32_t CROSSHAIR; extern int32_t CRYSTALAMMO; extern int32_t CYCLER; @@ -1232,22 +1233,6 @@ extern int32_t XXXSTACY; #define DYNAMICTILEMAP(Tilenum) (DynamicTileMap[Tilenum]) -#else /* if !defined DYNTILEREMAP_ENABLE */ - -#define G_ProcessDynamicTileMapping(x, y) ((void)(0)) - -#define inithashnames() ((void)0) -#define freehashnames() ((void)0) - -#include "names.h" -#undef SPACESHUTTLE -#undef CANNON -#undef CANNONBALLS - -#define DYNAMICTILEMAP(Tilenum) (Tilenum) - -#endif - END_DUKE_NS #endif // namesdyn_h__ diff --git a/source/duke3d/src/network.cpp b/source/duke3d/src/network.cpp index f0864e9c1..614b1a817 100644 --- a/source/duke3d/src/network.cpp +++ b/source/duke3d/src/network.cpp @@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "savegame.h" #include "input.h" #include "gamecvars.h" +#include "mapinfo.h" #include "enet.h" #include "m_crc32.h" @@ -1517,7 +1518,7 @@ static void P_RemovePlayer(int32_t p) voting = -1; } - Bstrcpy(apStrings[QUOTE_RESERVED2],recbuf); + quoteMgr.InitializeQuote(QUOTE_RESERVED2 ,recbuf); g_player[myconnectindex].ps->ftq = QUOTE_RESERVED2; g_player[myconnectindex].ps->fta = 180; } @@ -1692,28 +1693,28 @@ static void Net_ReceiveDisconnect(ENetEvent *event) switch (event->data) { case DISC_BAD_PASSWORD: - initprintf("Bad password.\n"); + initprintf("%s\n", GStrings("Bad password.")); return; case DISC_VERSION_MISMATCH: - initprintf("Version mismatch.\n"); + initprintf("%s\n", GStrings("Version mismatch.")); return; case DISC_INVALID: - initprintf("Invalid data detected.\n"); + initprintf("%s\n", GStrings("Invalid data detected.")); return; case DISC_SERVER_QUIT: - initprintf("The server is quitting.\n"); + initprintf("%s\n", GStrings("The server is quitting.")); return; case DISC_SERVER_FULL: - initprintf("The server is full.\n"); + initprintf("%s\n", GStrings("The server is full.\n")); return; case DISC_KICKED: - initprintf("You have been kicked from the server.\n"); + initprintf("%s\n", GStrings("You have been kicked from the server.\n")); return; case DISC_BANNED: - initprintf("You are banned from this server.\n"); + initprintf("%s\n", GStrings("You are banned from this server.\n")); return; default: - initprintf("Disconnected.\n"); + initprintf("%s\n", GStrings("Disconnected.\n")); return; } } @@ -1929,11 +1930,11 @@ static void Net_ReceiveMapVoteCancel(uint8_t *pbuf) if (voting == myconnectindex || voting != pbuf[1]) { - Bsprintf(tempbuf, "Vote Failed"); + Bsprintf(tempbuf, "%s", GStrings("Vote Failed")); } else if (voting == pbuf[1]) { - Bsprintf(tempbuf, "%s^00 has canceled the vote", g_player[voting].user_name); + Bsprintf(tempbuf, GStrings("canceledthevote"), g_player[voting].user_name); } G_AddUserQuote(tempbuf); @@ -1986,7 +1987,7 @@ static void Net_ReceiveUserMapName(uint8_t *pbuf, int32_t packbufleng) Bcorrectfilename(boardfilename, 0); if (boardfilename[0] != 0) { - if (testkopen(boardfilename, 0)) + if (fileSystem.FileExists(boardfilename)) { Bmemset(boardfilename, 0, sizeof(boardfilename)); Net_SendUserMapName(); @@ -2036,11 +2037,11 @@ static void Net_ReceiveMapVoteInitiate(uint8_t *pbuf) vote_episode = pendingnewgame.volume_number; vote_map = pendingnewgame.level_number; - Bsprintf(tempbuf, "%s^00 has called a vote to change map to %s (E%dL%d)", g_player[voting].user_name, - g_mapInfo[(uint8_t)(vote_episode * MAXLEVELS + vote_map)].name, vote_episode + 1, vote_map + 1); + Bsprintf(tempbuf, GStrings("votemap"), g_player[voting].user_name, + mapList[(uint8_t)(vote_episode * MAXLEVELS + vote_map)].DisplayName(), vote_episode + 1, vote_map + 1); G_AddUserQuote(tempbuf); - Bsprintf(tempbuf, "Press F1 to Accept, F2 to Decline"); + strcpy(tempbuf, GStrings("TXT_PRESSF1_F2")); G_AddUserQuote(tempbuf); for (playerIndex = MAXPLAYERS - 1; playerIndex >= 0; playerIndex--) @@ -2325,7 +2326,7 @@ static void Net_ReceiveNewGame(ENetEvent *event) ClientPlayerReady = 0; if ((vote_map + vote_episode + voting) != -3) - G_AddUserQuote("Vote Succeeded"); + G_AddUserQuote(GStrings("Vote Succeeded")); Bmemcpy(&pendingnewgame, event->packet->data, sizeof(newgame_t)); Net_StartNewGame(); @@ -4799,10 +4800,10 @@ void Net_SendClientInfo(void) l += 32; tempnetbuf[l++] = 0; - tempnetbuf[l++] = g_player[myconnectindex].ps->aim_mode = in_aimmode; + tempnetbuf[l++] = g_player[myconnectindex].ps->aim_mode = in_mousemode; tempnetbuf[l++] = g_player[myconnectindex].ps->auto_aim = cl_autoaim; tempnetbuf[l++] = g_player[myconnectindex].ps->weaponswitch = cl_weaponswitch; - tempnetbuf[l++] = g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = playercolor; + tempnetbuf[l++] = g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = G_CheckPlayerColor(playercolor); tempnetbuf[l++] = g_player[myconnectindex].pteam = playerteam; @@ -5051,7 +5052,7 @@ void Net_SendMessage(void) else if (g_chatPlayer == -1) { j = 50; - gametext_center(j, "Send message to..."); + gametext_center(j, GStrings("Send message to")); j += 8; for (TRAVERSE_CONNECT(i)) { diff --git a/source/duke3d/src/osdcmds.cpp b/source/duke3d/src/osdcmds.cpp index db76be6ec..92004f793 100644 --- a/source/duke3d/src/osdcmds.cpp +++ b/source/duke3d/src/osdcmds.cpp @@ -31,121 +31,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "menus.h" #include "savegame.h" #include "sbar.h" +#include "mapinfo.h" BEGIN_DUKE_NS struct osdcmd_cheatsinfo osdcmd_cheatsinfo_stat = { -1, 0, 0 }; -static int osdcmd_changelevel(osdcmdptr_t parm) -{ - int32_t volume=0,level; - char *p; - - if (!VOLUMEONE) - { - if (parm->numparms != 2) return OSDCMD_SHOWHELP; - - volume = strtol(parm->parms[0], &p, 10) - 1; - if (p[0]) return OSDCMD_SHOWHELP; - level = strtol(parm->parms[1], &p, 10) - 1; - if (p[0]) return OSDCMD_SHOWHELP; - } - else - { - if (parm->numparms != 1) return OSDCMD_SHOWHELP; - - level = strtol(parm->parms[0], &p, 10) - 1; - if (p[0]) return OSDCMD_SHOWHELP; - } - - if (volume < 0) return OSDCMD_SHOWHELP; - if (level < 0) return OSDCMD_SHOWHELP; - - if (!VOLUMEONE) - { - if (volume > g_volumeCnt) - { - OSD_Printf("changelevel: invalid volume number (range 1-%d)\n",g_volumeCnt); - return OSDCMD_OK; - } - } - - if (level > MAXLEVELS || g_mapInfo[volume *MAXLEVELS+level].filename == NULL) - { - OSD_Printf("changelevel: invalid level number\n"); - return OSDCMD_SHOWHELP; - } - - if (numplayers > 1) - { - /* - if (g_netServer) - Net_NewGame(volume,level); - else if (voting == -1) - { - ud.m_volume_number = volume; - m_level_number = level; - - if (g_player[myconnectindex].ps->i) - { - int32_t i; - - for (i=0; igm & MODE_GAME) - { - // in-game behave like a cheat - osdcmd_cheatsinfo_stat.cheatnum = CHEAT_SCOTTY; - osdcmd_cheatsinfo_stat.volume = volume; - osdcmd_cheatsinfo_stat.level = level; - } - else - { - // out-of-game behave like a menu command - osdcmd_cheatsinfo_stat.cheatnum = -1; - - ud.m_volume_number = volume; - m_level_number = level; - - ud.m_monsters_off = 0; - ud.monsters_off = 0; - - ud.m_respawn_items = 0; - ud.m_respawn_inventory = 0; - - ud.multimode = 1; - - G_NewGame_EnterLevel(); - } - - return OSDCMD_OK; -} - static int osdcmd_map(osdcmdptr_t parm) { char filename[BMAX_PATH]; @@ -160,7 +52,7 @@ static int osdcmd_map(osdcmdptr_t parm) maybe_append_ext(filename, sizeof(filename), parm->parms[0], ".map"); - if (!testkopen(filename,0)) + if (!fileSystem.FileExists(filename)) { OSD_Printf(OSD_ERROR "map: file \"%s\" not found.\n", filename); return OSDCMD_OK; @@ -172,48 +64,6 @@ static int osdcmd_map(osdcmdptr_t parm) if (numplayers > 1) { - /* - if (g_netServer) - { - Net_SendUserMapName(); - ud.m_volume_number = 0; - m_level_number = 7; - Net_NewGame(ud.m_volume_number, m_level_number); - } - else if (voting == -1) - { - Net_SendUserMapName(); - - ud.m_volume_number = 0; - m_level_number = 7; - - if (g_player[myconnectindex].ps->i) - { - int32_t i; - - for (i=0; inumparms == 1) - { - int32_t sel = G_GetMusicIdx(parm->parms[0]); - - if (sel == -1) - return OSDCMD_SHOWHELP; - - if (sel == -2) - { - OSD_Printf("%s is not a valid episode/level number pair\n", parm->parms[0]); - return OSDCMD_OK; - } - - if (!S_TryPlayLevelMusic(sel)) - { - G_PrintCurrentMusic(); - } - else - { - OSD_Printf("No music defined for %s\n", parm->parms[0]); - } - - return OSDCMD_OK; - } - - return OSDCMD_SHOWHELP; -} - int osdcmd_restartmap(osdcmdptr_t UNUSED(parm)) { UNREFERENCED_CONST_PARAMETER(parm); @@ -428,11 +243,6 @@ static int osdcmd_vidmode(osdcmdptr_t parm) return OSDCMD_OK; } -#ifdef LUNATIC -// Returns: INT32_MIN if no such CON label, its value else. -LUNATIC_CB int32_t (*El_GetLabelValue)(const char *label); -#endif - static int osdcmd_spawn(osdcmdptr_t parm) { int32_t picnum = 0; @@ -476,12 +286,6 @@ static int osdcmd_spawn(osdcmdptr_t parm) else { int32_t i; -#ifdef LUNATIC - i = g_labelCnt; - picnum = El_GetLabelValue(parm->parms[0]); - if (picnum != INT32_MIN) - i = !i; -#else int32_t j; for (j=0; j<2; j++) @@ -499,7 +303,6 @@ static int osdcmd_spawn(osdcmdptr_t parm) if (i < g_labelCnt) break; } -#endif if (i==g_labelCnt) { OSD_Printf("spawn: Invalid tile label given\n"); @@ -534,7 +337,6 @@ static int osdcmd_spawn(osdcmdptr_t parm) return OSDCMD_OK; } -#if !defined LUNATIC static int osdcmd_setvar(osdcmdptr_t parm) { if (numplayers > 1) @@ -627,59 +429,6 @@ static int osdcmd_setactorvar(osdcmdptr_t parm) return OSDCMD_OK; } -#else -static int osdcmd_lua(osdcmdptr_t parm) -{ - // Should be used like - // lua "lua code..." - // (the quotes making the whole string passed as one argument) - - int32_t ret; - - if (parm->numparms != 1) - return OSDCMD_SHOWHELP; - - if (!L_IsInitialized(&g_ElState)) - { - OSD_Printf("Lua state is not initialized.\n"); - return OSDCMD_OK; - } - - // TODO: "=" as shorthand for "print()", like in the - // stand-alone Lua interpreter? - // TODO: reserve some table to explicitly store stuff on the top level, for - // debugging convenience? - - // For the 'lua' OSD command, don't make errors appear on-screen: - el_addNewErrors = 0; - ret = L_RunString(&g_ElState, parm->parms[0], -1, "console"); - el_addNewErrors = 1; - - if (ret != 0) - OSD_Printf("Error running the Lua code (error code %d)\n", ret); - - return OSDCMD_OK; -} -#endif - -static int osdcmd_cmenu(osdcmdptr_t parm) -{ - if (parm->numparms != 1) - return OSDCMD_SHOWHELP; - - if (numplayers > 1) - { - OSD_Printf("Command not allowed in multiplayer\n"); - return OSDCMD_OK; - } - - if ((g_player[myconnectindex].ps->gm & MODE_MENU) != MODE_MENU) - Menu_Open(myconnectindex); - - Menu_Change(Batol(parm->parms[0])); - - return OSDCMD_OK; -} @@ -788,62 +537,6 @@ void onvideomodechange(int32_t newmode) g_crosshairSum = -1; } -static int osdcmd_quicksave(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - if (!(g_player[myconnectindex].ps->gm & MODE_GAME)) - OSD_Printf("quicksave: not in a game.\n"); - else g_doQuickSave = 1; - return OSDCMD_OK; -} - -static int osdcmd_quickload(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - if (!(g_player[myconnectindex].ps->gm & MODE_GAME)) - OSD_Printf("quickload: not in a game.\n"); - else g_doQuickSave = 2; - return OSDCMD_OK; -} - -static int osdcmd_screenshot(osdcmdptr_t parm) -{ - videoCaptureScreen(); - return OSDCMD_OK; -} - -#if 0 -static int osdcmd_savestate(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_PARAMETER(parm); - G_SaveMapState(); - return OSDCMD_OK; -} - -static int osdcmd_restorestate(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_PARAMETER(parm); - G_RestoreMapState(); - return OSDCMD_OK; -} -#endif - -#ifdef DEBUGGINGAIDS -static int osdcmd_inittimer(osdcmdptr_t parm) -{ - if (parm->numparms != 1) - { - OSD_Printf("%dHz timer\n",g_timerTicsPerSecond); - return OSDCMD_SHOWHELP; - } - - G_InitTimer(Batol(parm->parms[0])); - - OSD_Printf("%s\n",parm->raw); - return OSDCMD_OK; -} -#endif - static int osdcmd_dumpmapstate(osdfuncparm_t const * const) { @@ -1017,12 +710,6 @@ static int osdcmd_kickban(osdcmdptr_t parm) } #endif -static int osdcmd_purgesaves(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - G_DeleteOldSaves(); - return OSDCMD_OK; -} static int osdcmd_printtimes(osdcmdptr_t UNUSED(parm)) { @@ -1107,41 +794,29 @@ int32_t registerosdcommands(void) OSD_RegisterFunction("playerinfo", "Prints information about the current player", osdcmd_playerinfo); #endif - if (VOLUMEONE) - OSD_RegisterFunction("changelevel","changelevel : warps to the given level", osdcmd_changelevel); - else + if (!VOLUMEONE) { - OSD_RegisterFunction("changelevel","changelevel : warps to the given level", osdcmd_changelevel); OSD_RegisterFunction("map","map : loads the given user map", osdcmd_map); OSD_RegisterFunction("demo","demo : starts the given demo", osdcmd_demo); } - OSD_RegisterFunction("cmenu","cmenu <#>: jumps to menu", osdcmd_cmenu); OSD_RegisterFunction("crosshaircolor","crosshaircolor: changes the crosshair color", osdcmd_crosshaircolor); OSD_RegisterFunction("give","give : gives requested item", osdcmd_give); OSD_RegisterFunction("god","god: toggles god mode", osdcmd_god); OSD_RegisterFunction("activatecheat","activatecheat : activates a cheat code", osdcmd_activatecheat); - OSD_RegisterFunction("music","music EL: change music", osdcmd_music); - OSD_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip); OSD_RegisterFunction("printtimes", "printtimes: prints VM timing statistics", osdcmd_printtimes); - OSD_RegisterFunction("purgesaves", "purgesaves: deletes obsolete and unreadable save files", osdcmd_purgesaves); - - OSD_RegisterFunction("quicksave","quicksave: performs a quick save", osdcmd_quicksave); - OSD_RegisterFunction("quickload","quickload: performs a quick load", osdcmd_quickload); - OSD_RegisterFunction("restartmap", "restartmap: restarts the current map", osdcmd_restartmap); OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound); OSD_RegisterFunction("addlogvar","addlogvar : prints the value of a gamevar", osdcmd_addlogvar); OSD_RegisterFunction("setvar","setvar : sets the value of a gamevar", osdcmd_setvar); OSD_RegisterFunction("setvarvar","setvarvar : sets the value of to ", osdcmd_setvar); OSD_RegisterFunction("setactorvar","setactorvar : sets the value of 's to ", osdcmd_setactorvar); - OSD_RegisterFunction("screenshot","screenshot [format]: takes a screenshot.", osdcmd_screenshot); OSD_RegisterFunction("spawn","spawn [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",osdcmd_spawn); diff --git a/source/duke3d/src/player.cpp b/source/duke3d/src/player.cpp index 9b354139e..c15ea143f 100644 --- a/source/duke3d/src/player.cpp +++ b/source/duke3d/src/player.cpp @@ -2887,7 +2887,6 @@ enddisplayweapon: #define MAXANGVEL 1024 #define MAXHORIZ 256 -int32_t g_myAimStat = 0, g_oldAimStat = 0; int32_t mouseyaxismode = -1; void P_GetInput(int const playerNum) @@ -2895,7 +2894,7 @@ void P_GetInput(int const playerNum) auto const pPlayer = g_player[playerNum].ps; ControlInfo info; - if ((pPlayer->gm & (MODE_MENU|MODE_TYPE)) || (ud.pause_on && !inputState.GetKeyStatus(sc_Pause))) + if (g_cheatBufLen > 1 || (pPlayer->gm & (MODE_MENU|MODE_TYPE)) || (ud.pause_on && !inputState.GetKeyStatus(sc_Pause))) { if (!(pPlayer->gm&MODE_MENU)) CONTROL_GetInput(&info); @@ -2910,43 +2909,10 @@ void P_GetInput(int const playerNum) D_ProcessEvents(); - if (in_aimmode) - g_MyAimMode = buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - else - { - g_oldAimStat = g_myAimStat; - g_myAimStat = buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - - if (g_myAimStat > g_oldAimStat) - { - g_MyAimMode ^= 1; - P_DoQuote(QUOTE_MOUSE_AIMING_OFF + g_MyAimMode, pPlayer); - } - } + bool mouseaim = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); CONTROL_GetInput(&info); - if (in_mousedeadzone) - { - if (info.mousey > 0) - info.mousey = max(info.mousey - in_mousedeadzone, 0); - else if (info.mousey < 0) - info.mousey = min(info.mousey + in_mousedeadzone, 0); - - if (info.mousex > 0) - info.mousex = max(info.mousex - in_mousedeadzone, 0); - else if (info.mousex < 0) - info.mousex = min(info.mousex + in_mousedeadzone, 0); - } - - if (in_mousebias) - { - if (klabs(info.mousex) > klabs(info.mousey)) - info.mousey = tabledivide32_noinline(info.mousey, in_mousebias); - else - info.mousex = tabledivide32_noinline(info.mousex, in_mousebias); - } - // JBF: Run key behaviour is selectable int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); int const turnAmount = playerRunning ? (NORMALTURN << 1) : NORMALTURN; @@ -2971,7 +2937,7 @@ void P_GetInput(int const playerNum) input.q16avel += fix16_from_int(info.dyaw) / analogExtent * (analogTurnAmount << 1); } - if (g_MyAimMode) + if (mouseaim) input.q16horz = fix16_div(fix16_from_int(info.mousey), F16(64)); else input.fvel = -(info.mousey >> 6); @@ -3058,20 +3024,23 @@ void P_GetInput(int const playerNum) int const sectorLotag = pPlayer->cursectnum != -1 ? sector[pPlayer->cursectnum].lotag : 0; int const crouchable = sectorLotag != 2 && (sectorLotag != 1 || pPlayer->spritebridge); - if (pPlayer->cheat_phase == 0 && buttonMap.ButtonDown(gamefunc_Toggle_Crouch)) + if (pPlayer->cheat_phase < 1) { - pPlayer->crouch_toggle = !pPlayer->crouch_toggle && crouchable; + if (buttonMap.ButtonDown(gamefunc_Toggle_Crouch)) + { + pPlayer->crouch_toggle = !pPlayer->crouch_toggle && crouchable; - if (crouchable) - buttonMap.ClearButton(gamefunc_Toggle_Crouch); + if (crouchable) + buttonMap.ClearButton(gamefunc_Toggle_Crouch); } - if (buttonMap.ButtonDown(gamefunc_Crouch) || buttonMap.ButtonDown(gamefunc_Jump) || pPlayer->jetpack_on || (!crouchable && pPlayer->on_ground)) - pPlayer->crouch_toggle = 0; + if (buttonMap.ButtonDown(gamefunc_Crouch) || buttonMap.ButtonDown(gamefunc_Jump) || pPlayer->jetpack_on || (!crouchable && pPlayer->on_ground)) + pPlayer->crouch_toggle = 0; - int const crouching = buttonMap.ButtonDown(gamefunc_Crouch) || buttonMap.ButtonDown(gamefunc_Toggle_Crouch) || pPlayer->crouch_toggle; + int const crouching = buttonMap.ButtonDown(gamefunc_Crouch) || buttonMap.ButtonDown(gamefunc_Toggle_Crouch) || pPlayer->crouch_toggle; - localInput.bits |= (buttonMap.ButtonDown(gamefunc_Jump) << SK_JUMP) | (crouching << SK_CROUCH); + localInput.bits |= (buttonMap.ButtonDown(gamefunc_Jump) << SK_JUMP) | (crouching << SK_CROUCH); + } localInput.bits |= (buttonMap.ButtonDown(gamefunc_Aim_Up) || (buttonMap.ButtonDown(gamefunc_Dpad_Aiming) && input.fvel > 0)) << SK_AIM_UP; localInput.bits |= (buttonMap.ButtonDown(gamefunc_Aim_Down) || (buttonMap.ButtonDown(gamefunc_Dpad_Aiming) && input.fvel < 0)) << SK_AIM_DOWN; @@ -3094,7 +3063,7 @@ void P_GetInput(int const playerNum) localInput.bits |= buttonMap.ButtonDown(gamefunc_Quick_Kick) << SK_QUICK_KICK; localInput.bits |= buttonMap.ButtonDown(gamefunc_TurnAround) << SK_TURNAROUND; - localInput.bits |= (g_MyAimMode << SK_AIMMODE); + localInput.bits |= (mouseaim << SK_AIMMODE); localInput.bits |= (g_gameQuit << SK_GAMEQUIT); localInput.bits |= inputState.GetKeyStatus(sc_Pause) << SK_PAUSE; localInput.bits |= ((uint32_t)inputState.GetKeyStatus(sc_Escape)) << SK_ESCAPE; @@ -3789,18 +3758,18 @@ void P_FragPlayer(int playerNum) if (playerNum == screenpeek) { - Bsprintf(apStrings[QUOTE_RESERVED], "Killed by %s", &g_player[pPlayer->frag_ps].user_name[0]); + quoteMgr.FormatQuote(QUOTE_RESERVED, "Killed by %s", &g_player[pPlayer->frag_ps].user_name[0]); P_DoQuote(QUOTE_RESERVED, pPlayer); } else { - Bsprintf(apStrings[QUOTE_RESERVED2], "Killed %s", &g_player[playerNum].user_name[0]); + quoteMgr.FormatQuote(QUOTE_RESERVED2, "Killed %s", &g_player[playerNum].user_name[0]); P_DoQuote(QUOTE_RESERVED2, g_player[pPlayer->frag_ps].ps); } if (cl_obituaries) { - Bsprintf(tempbuf, apStrings[OBITQUOTEINDEX + (krand() % g_numObituaries)], + Bsprintf(tempbuf, quoteMgr.GetQuote(OBITQUOTEINDEX + (krand() % g_numObituaries)), &g_player[pPlayer->frag_ps].user_name[0], &g_player[playerNum].user_name[0]); G_AddUserQuote(tempbuf); } @@ -3813,14 +3782,14 @@ void P_FragPlayer(int playerNum) { pPlayer->fraggedself++; if ((unsigned)pPlayer->wackedbyactor < MAXTILES && A_CheckEnemyTile(sprite[pPlayer->wackedbyactor].picnum)) - Bsprintf(tempbuf, apStrings[OBITQUOTEINDEX + (krand() % g_numObituaries)], "A monster", + Bsprintf(tempbuf, quoteMgr.GetQuote(OBITQUOTEINDEX + (krand() % g_numObituaries)), "A monster", &g_player[playerNum].user_name[0]); else if (actor[pPlayer->i].picnum == NUKEBUTTON) Bsprintf(tempbuf, "^02%s^02 tried to leave", &g_player[playerNum].user_name[0]); else { // random suicide death string - Bsprintf(tempbuf, apStrings[SUICIDEQUOTEINDEX + (krand() % g_numSelfObituaries)], + Bsprintf(tempbuf, quoteMgr.GetQuote(SUICIDEQUOTEINDEX + (krand() % g_numSelfObituaries)), &g_player[playerNum].user_name[0]); } } @@ -4925,7 +4894,9 @@ void P_ProcessInput(int playerNum) pPlayer->oq16ang = pPlayer->q16ang; updatesector(pPlayer->pos.x, pPlayer->pos.y, &pPlayer->cursectnum); - pushmove(&pPlayer->pos, &pPlayer->cursectnum, pPlayer->clipdist - 1, (4L<<8), stepHeight, CLIPMASK0); + + if (!ud.noclip) + pushmove(&pPlayer->pos, &pPlayer->cursectnum, pPlayer->clipdist - 1, (4L<<8), stepHeight, CLIPMASK0); if (pPlayer->one_eighty_count < 0) { @@ -5642,7 +5613,6 @@ int portableBackupSave(const char * path, const char * name, int volume, int lev sjson_node * root = sjson_mkobject(ctx); sjson_put_string(ctx, root, "name", name); - // sjson_put_string(ctx, root, "map", currentboardfilename); sjson_put_int(ctx, root, "volume", volume); sjson_put_int(ctx, root, "level", level); sjson_put_int(ctx, root, "skill", ud.player_skill); diff --git a/source/duke3d/src/premap.cpp b/source/duke3d/src/premap.cpp index 180ae4f38..a48db358e 100644 --- a/source/duke3d/src/premap.cpp +++ b/source/duke3d/src/premap.cpp @@ -29,6 +29,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "menus.h" #include "savegame.h" #include "statistics.h" +#include "menu/menu.h" +#include "mapinfo.h" +#include "cmdlib.h" BEGIN_DUKE_NS static uint8_t precachehightile[2][(MAXTILES+7)>>3]; @@ -328,7 +331,8 @@ static void G_DemoLoadScreen(const char *statustext, int const loadScreenTile, i return; } - menutext_center(105, "Loading..."); + FStringf msg("%s...", GStrings("TXT_LOADING")); + menutext_center(105, msg); if (statustext) gametext_center_number(180, statustext); @@ -371,15 +375,13 @@ static void G_DoLoadScreen(const char *statustext, int percent) if (boardfilename[0] != 0 && ud.level_number == 7 && ud.volume_number == 0) { - menutext_center(90, "Loading User Map"); + menutext_center(90, GStrings("TXT_LOADUM")); gametext_center_shade_pal(90+10, boardfilename, 14, 2); } else { - menutext_center(90, "Loading"); - - if (g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name != NULL) - menutext_center(90+16+8, g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name); + menutext_center(90, GStrings("TXT_LOADING")); + menutext_center(90+16+8, mapList[(ud.volume_number*MAXLEVELS) + ud.level_number].DisplayName()); } #ifndef EDUKE32_TOUCH_DEVICES @@ -417,7 +419,7 @@ void G_CacheMapData(void) if (ud.recstat == 2) return; - S_TryPlaySpecialMusic(MUS_LOADING); + //S_TryPlaySpecialMusic(MUS_LOADING); uint32_t const cacheStartTime = timerGetTicks(); @@ -1338,12 +1340,6 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum) ud.secretlevel = 0; ud.skill_voice = -1; ud.volume_number = volumeNum; - STAT_StartNewGame(g_volumeNames[volumeNum], skillNum); - - g_lastAutoSaveArbitraryID = -1; - g_lastautosave.reset(); - g_lastusersave.reset(); - g_quickload = nullptr; // we don't want the intro to play after the multiplayer setup screen if ((!g_netServer && ud.multimode < 2) && !Menu_HaveUserMap() @@ -1358,7 +1354,7 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum) #endif p0.gm = 0; - Menu_Close(0); + M_ClearMenus(); #if !defined LUNATIC Gv_ResetVars(); @@ -1625,13 +1621,11 @@ int G_FindLevelByFile(const char *fileName) { int i = 0; - for (auto &levelNum : g_mapInfo) + for (auto &levelNum : mapList) { i++; - if (levelNum.filename == NULL) - continue; - else if (!Bstrcasecmp(fileName, levelNum.filename)) + if (levelNum.fileName.CompareNoCase(fileName) == 0) return i-1; } @@ -1695,20 +1689,18 @@ void G_SetupFilenameBasedMusic(char *nameBuf, const char *fileName) { char *p; char const *exts[] = { -#ifdef HAVE_FLAC "flac", -#endif -#ifdef HAVE_VORBIS "ogg", -#endif -#ifdef HAVE_XMP + "mp3", "xm", "mod", "it", "s3m", "mtm", -#endif - "mid" + "mid", + "hmp", + "hmi", + "xmi" }; Bstrncpy(nameBuf, fileName, BMAX_PATH); @@ -1721,31 +1713,32 @@ void G_SetupFilenameBasedMusic(char *nameBuf, const char *fileName) p[0] = '.'; } + // Test if a real file with this name exists with all known extensions for music. for (auto & ext : exts) { Bmemcpy(p+1, ext, Bstrlen(ext) + 1); - if (testkopen(nameBuf, 0)) + if (FileExists(nameBuf)) { - realloc_copy(&g_mapInfo[USERMAPMUSICFAKESLOT].musicfn, nameBuf); + userMapRecord.music = nameBuf; return; } } - char const * usermapMusic = g_mapInfo[MUS_USERMAP].musicfn; - if (usermapMusic != nullptr) + auto &usermapMusic = mapList[MUS_USERMAP].music; + if (usermapMusic.IsNotEmpty()) { - realloc_copy(&g_mapInfo[USERMAPMUSICFAKESLOT].musicfn, usermapMusic); + userMapRecord.music = usermapMusic; return; } #ifndef EDUKE32_STANDALONE if (!FURY) { - char const * e1l8 = g_mapInfo[7].musicfn; - if (e1l8 != nullptr) + auto &e1l8 = mapList[7].music; + if (e1l8.IsNotEmpty()) { - realloc_copy(&g_mapInfo[USERMAPMUSICFAKESLOT].musicfn, e1l8); + userMapRecord.music = e1l8; return; } } @@ -1820,13 +1813,13 @@ int G_EnterLevel(int gameMode) int const mapidx = (ud.volume_number * MAXLEVELS) + ud.level_number; - Bassert((unsigned)mapidx < ARRAY_SIZE(g_mapInfo)); + Bassert((unsigned)mapidx < ARRAY_SIZE(mapList)); - auto &m = g_mapInfo[mapidx]; + auto& mm = mapList[mapidx]; if (VOLUMEONE || !Menu_HaveUserMap()) { - if (m.name == NULL || m.filename == NULL) + if (mm.fileName.IsEmpty()) { OSD_Printf(OSDTEXT_RED "Map E%dL%d not defined!\n", ud.volume_number+1, ud.level_number+1); return 1; @@ -1836,7 +1829,8 @@ int G_EnterLevel(int gameMode) int const ssize = ud.screen_size; ud.screen_size = 0; - G_DoLoadScreen("Loading map . . .", -1); + FStringf msg("%s . . .", GStrings("TXT_LOADMAP")); + G_DoLoadScreen(msg, -1); G_UpdateScreenArea(); ud.screen_size = ssize; @@ -1855,19 +1849,23 @@ int G_EnterLevel(int gameMode) OSD_Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", boardfilename); return 1; } - STAT_NewLevel(boardfilename); + userMapRecord.name = ""; + userMapRecord.SetFileName(boardfilename); + currentLevel = &userMapRecord; + STAT_NewLevel(boardfilename); G_LoadMapHack(levelName, boardfilename); G_SetupFilenameBasedMusic(levelName, boardfilename); } - else if (engineLoadBoard(m.filename, VOLUMEONE, &p0.pos, &playerAngle, &p0.cursectnum) < 0) + else if (engineLoadBoard(mm.fileName, VOLUMEONE, &p0.pos, &playerAngle, &p0.cursectnum) < 0) { - OSD_Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", m.filename); + OSD_Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", mm.fileName.GetChars()); return 1; } else { - STAT_NewLevel(m.filename); - G_LoadMapHack(levelName, m.filename); + currentLevel = &mm; + STAT_NewLevel(mm.fileName); + G_LoadMapHack(levelName, mm.fileName); } p0.q16ang = fix16_from_int(playerAngle); @@ -1888,7 +1886,7 @@ int G_EnterLevel(int gameMode) G_ResetAllPlayers(); G_CollectSpawnPoints(gameMode); - ud.playerbest = CONFIG_GetMapBestTime(Menu_HaveUserMap() ? boardfilename : m.filename, g_loadedMapHack.md4); + ud.playerbest = CONFIG_GetMapBestTime(Menu_HaveUserMap() ? boardfilename : mm.fileName.GetChars(), g_loadedMapHack.md4); // G_FadeLoad(0,0,0, 252,0, -28, 4, -1); G_CacheMapData(); @@ -1900,23 +1898,15 @@ int G_EnterLevel(int gameMode) { S_PlayLevelMusicOrNothing(USERMAPMUSICFAKESLOT); } - else if (g_mapInfo[g_musicIndex].musicfn == NULL || m.musicfn == NULL || - strcmp(g_mapInfo[g_musicIndex].musicfn, m.musicfn) || g_musicSize == 0 || ud.last_level == -1) - { - S_PlayLevelMusicOrNothing(mapidx); - } - else - { - S_ContinueLevelMusic(); - } + else S_PlayLevelMusicOrNothing(mapidx); } + M_ClearMenus(); if (gameMode & (MODE_GAME|MODE_EOL)) { for (int TRAVERSE_CONNECT(i)) { g_player[i].ps->gm = MODE_GAME; - Menu_Close(i); } } else if (gameMode & MODE_RESTART) @@ -1950,8 +1940,6 @@ int G_EnterLevel(int gameMode) G_ResetTimers(0); // Here we go - Bmemcpy(currentboardfilename, boardfilename, BMAX_PATH); - G_CheckIfStateless(); for (int TRAVERSE_CONNECT(i)) @@ -1961,11 +1949,11 @@ int G_EnterLevel(int gameMode) } if (G_HaveUserMap()) - OSD_Printf(OSDTEXT_YELLOW "User Map: %s\n", boardfilename); + OSD_Printf(OSDTEXT_YELLOW "%s: %s\n", GStrings("TXT_USERMAP"), boardfilename); else if (FURY) - OSD_Printf(OSDTEXT_YELLOW "Entering: %s\n", m.name); + OSD_Printf(OSDTEXT_YELLOW "%s: %s\n", GStrings("TXT_ENTERING"), mm.DisplayName()); else - OSD_Printf(OSDTEXT_YELLOW "E%dL%d: %s\n", ud.volume_number + 1, ud.level_number + 1, m.name); + OSD_Printf(OSDTEXT_YELLOW "E%dL%d: %s\n", ud.volume_number + 1, ud.level_number + 1, mm.DisplayName()); g_restorePalette = -1; diff --git a/source/duke3d/src/quotes.h b/source/duke3d/src/quotes.h index b75ff9d13..50b9dc1c2 100644 --- a/source/duke3d/src/quotes.h +++ b/source/duke3d/src/quotes.h @@ -23,8 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef quotes_h_ #define quotes_h_ -#define MAXQUOTES 16384 -#define MAXQUOTELEN 128 +#include "quotemgr.h" + #define OBITQUOTEINDEX (MAXQUOTES-128) #define SUICIDEQUOTEINDEX (MAXQUOTES-32) @@ -89,7 +89,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define QUOTE_RESERVED 115 #define QUOTE_RESERVED2 116 #define QUOTE_RESERVED3 117 -#define QUOTE_SAVE_DEAD NOBETAQUOTE(118) +#define QUOTE_SAVE_DEAD 118 #define QUOTE_CHEAT_ALL_WEAPONS NOBETAQUOTE(119) #define QUOTE_CHEAT_ALL_INV NOBETAQUOTE(120) #define QUOTE_CHEAT_ALL_KEYS NOBETAQUOTE(121) diff --git a/source/duke3d/src/savegame.cpp b/source/duke3d/src/savegame.cpp index 1c195fd00..9c62f961a 100644 --- a/source/duke3d/src/savegame.cpp +++ b/source/duke3d/src/savegame.cpp @@ -30,14 +30,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "i_specialpaths.h" #include "gamecontrol.h" #include "version.h" -#include "statistics.h" -#include "secrets.h" #include "savegamehelp.h" +#include "menu/menu.h" +#include "mapinfo.h" +#include "z_music.h" BEGIN_DUKE_NS static OutputFileCounter savecounter; -char previousboardfilename[BMAX_PATH]; // For storing pointers in files. // back_p==0: ptr -> "small int" @@ -141,16 +141,9 @@ void G_ResetInterpolations(void) G_SetInterpolation(g_animatePtr[i]); } -savebrief_t g_lastautosave, g_lastusersave, g_freshload; -int32_t g_lastAutoSaveArbitraryID = -1; +int32_t g_fakeSaveID = -1; bool g_saveRequested; -savebrief_t * g_quickload; -menusave_t * g_menusaves; -uint16_t g_nummenusaves; - -static menusave_t * g_internalsaves; -static uint16_t g_numinternalsaves; static FileReader *OpenSavegame(const char *fn) { @@ -158,13 +151,7 @@ static FileReader *OpenSavegame(const char *fn) { return nullptr; } - auto file = ReadSavegameChunk("DEMOLITION_ED"); - if (!file.isOpen()) - { - FinishSavegameRead(); - return nullptr; - } - file = ReadSavegameChunk("snapshot.dat"); + auto file = ReadSavegameChunk("snapshot.dat"); if (!file.isOpen()) { FinishSavegameRead(); @@ -173,145 +160,6 @@ static FileReader *OpenSavegame(const char *fn) return new FileReader(std::move(file)); } -static void ReadSaveGameHeaders_CACHE1D(TArray &saves) -{ - savehead_t h; - - for (FString &save : saves) - { - auto fil = OpenSavegame(save); - if (!fil) - continue; - - menusave_t & msv = g_internalsaves[g_numinternalsaves]; - - msv.brief.isExt = 0; - - int32_t k = sv_loadheader(*fil, 0, &h); - delete fil; - if (k) - { - if (k < 0) - msv.isUnreadable = 1; - else - { - if (FURY) - { - auto extfil = ReadSavegameChunk("ext.json"); - if (extfil.isOpen()) - { - msv.brief.isExt = 1; - } - } - } - msv.isOldVer = 1; - } - else - msv.isOldVer = 0; - - msv.isAutoSave = h.isAutoSave(); - - strncpy(msv.brief.path, save.GetChars(), ARRAY_SIZE(msv.brief.path)); - ++g_numinternalsaves; - - if (k >= 0 && h.savename[0] != '\0') - { - memcpy(msv.brief.name, h.savename, ARRAY_SIZE(msv.brief.name)); - } - else - msv.isUnreadable = 1; - - } - FinishSavegameRead(); -} - -static void ReadSaveGameHeaders_Internal(void) -{ - FString pattern = M_GetSavegamesPath() + "*.bsv"; - TArray saves; - D_AddWildFile(saves, pattern); - // potentially overallocating but programmatically simple - int const numfiles = saves.Size(); - size_t const internalsavesize = sizeof(menusave_t) * numfiles; - - g_internalsaves = (menusave_t *)Xrealloc(g_internalsaves, internalsavesize); - - for (int x = 0; x < numfiles; ++x) - g_internalsaves[x].clear(); - - g_numinternalsaves = 0; - ReadSaveGameHeaders_CACHE1D(saves); - - g_nummenusaves = 0; - for (int x = g_numinternalsaves-1; x >= 0; --x) - { - menusave_t & msv = g_internalsaves[x]; - if (!msv.isUnreadable) - { - ++g_nummenusaves; - } - } - size_t const menusavesize = sizeof(menusave_t) * g_nummenusaves; - - g_menusaves = (menusave_t *)Xrealloc(g_menusaves, menusavesize); - - for (int x = 0; x < g_nummenusaves; ++x) - g_menusaves[x].clear(); - - for (int x = g_numinternalsaves-1, y = 0; x >= 0; --x) - { - menusave_t & msv = g_internalsaves[x]; - if (!msv.isUnreadable) - { - g_menusaves[y++] = msv; - } - } - - for (int x = g_numinternalsaves-1; x >= 0; --x) - { - char const * const path = g_internalsaves[x].brief.path; - int const pathlen = Bstrlen(path); - if (pathlen < 12) - continue; - char const * const fn = path + (pathlen-12); - if (fn[0] == 's' && fn[1] == 'a' && fn[2] == 'v' && fn[3] == 'e' && - isdigit(fn[4]) && isdigit(fn[5]) && isdigit(fn[6]) && isdigit(fn[7])) - { - char number[5]; - memcpy(number, fn+4, 4); - number[4] = '\0'; - savecounter.count = Batoi(number)+1; - break; - } - } -} - -void ReadSaveGameHeaders(void) -{ - ReadSaveGameHeaders_Internal(); - - if (!cl_autosavedeletion) - return; - - bool didDelete = false; - int numautosaves = 0; - for (int x = 0; x < g_nummenusaves; ++x) - { - menusave_t & msv = g_menusaves[x]; - if (!msv.isAutoSave) - continue; - if (numautosaves >= cl_maxautosaves) - { - G_DeleteSave(msv.brief); - didDelete = true; - } - ++numautosaves; - } - - if (didDelete) - ReadSaveGameHeaders_Internal(); -} - int32_t G_LoadSaveHeaderNew(char const *fn, savehead_t *saveh) { FileReader ssfil; @@ -323,24 +171,6 @@ int32_t G_LoadSaveHeaderNew(char const *fn, savehead_t *saveh) if (i < 0) goto corrupt; - ssfil = ReadSavegameChunk("screenshot.dat"); - - TileFiles.tileCreate(TILE_LOADSHOT, 200, 320); - if (ssfil.isOpen()) - { - if (ssfil.Read(tileData(TILE_LOADSHOT), 320 * 200) != 320 * 200) - { - OSD_Printf("G_LoadSaveHeaderNew(): failed reading screenshot in \"%s\"\n", fn); - goto corrupt; - } - } - else - { - Bmemset(tileData(TILE_LOADSHOT), 0, 320*200); - } - ssfil.Close(); - tileInvalidate(TILE_LOADSHOT, 0, 255); - delete fil; FinishSavegameRead(); return 0; @@ -354,20 +184,18 @@ corrupt: static void sv_postudload(); -// hack -static int different_user_map; - - // XXX: keyboard input 'blocked' after load fail? (at least ESC?) -int32_t G_LoadPlayer(savebrief_t & sv) +int32_t G_LoadPlayer(FSaveGameNode *sv) { - if (sv.isExt) + char workbuffer[BMAX_PATH]; + + if (sv->bIsExt) { int volume = -1; int level = -1; int skill = -1; - auto fil = OpenSavegame(sv.path); + auto fil = OpenSavegame(sv->Filename); if (!fil) return -1; { @@ -458,23 +286,18 @@ int32_t G_LoadPlayer(savebrief_t & sv) int const mapIdx = volume*MAXLEVELS + level; if (boardfilename[0]) - Bstrcpy(currentboardfilename, boardfilename); - else if (g_mapInfo[mapIdx].filename) - Bstrcpy(currentboardfilename, g_mapInfo[mapIdx].filename); + strcpy(workbuffer, boardfilename); + else if (mapList[mapIdx].fileName.IsNotEmpty()) + strcpy(workbuffer, mapList[mapIdx].fileName); - if (currentboardfilename[0]) + if (workbuffer[0]) { // only setup art if map differs from previous - if (!previousboardfilename[0] || Bstrcmp(previousboardfilename, currentboardfilename)) - artSetupMapArt(currentboardfilename); - Bstrcpy(previousboardfilename, currentboardfilename); - append_ext_UNSAFE(currentboardfilename, ".mhk"); - engineLoadMHK(currentboardfilename); + artSetupMapArt(workbuffer); + append_ext_UNSAFE(workbuffer, ".mhk"); + engineLoadMHK(workbuffer); } - - currentboardfilename[0] = '\0'; - // G_NewGame_EnterLevel(); } @@ -493,8 +316,6 @@ int32_t G_LoadPlayer(savebrief_t & sv) ud.skill_voice = -1; ud.volume_number = volume; - g_lastAutoSaveArbitraryID = -1; - #ifdef EDUKE32_TOUCH_DEVICES p0.zoom = 360; #else @@ -502,7 +323,7 @@ int32_t G_LoadPlayer(savebrief_t & sv) #endif p0.gm = 0; - Menu_Close(0); + M_ClearMenus(); #if !defined LUNATIC Gv_ResetVars(); @@ -604,7 +425,7 @@ int32_t G_LoadPlayer(savebrief_t & sv) return 0; } - auto fil = OpenSavegame(sv.path); + auto fil = OpenSavegame(sv->Filename); if (!fil) return -1; @@ -655,36 +476,31 @@ int32_t G_LoadPlayer(savebrief_t & sv) ud.m_player_skill = h.skill; // NOTE: Bmemcpy needed for SAVEGAME_MUSIC. - EDUKE32_STATIC_ASSERT(sizeof(boardfilename) == sizeof(h.boardfn)); - different_user_map = Bstrcmp(boardfilename, h.boardfn); - Bmemcpy(boardfilename, h.boardfn, sizeof(boardfilename)); + strcpy(boardfilename, currentLevel->fileName); int const mapIdx = h.volnum*MAXLEVELS + h.levnum; - if (boardfilename[0]) - Bstrcpy(currentboardfilename, boardfilename); - else if (g_mapInfo[mapIdx].filename) - Bstrcpy(currentboardfilename, g_mapInfo[mapIdx].filename); + if (boardfilename[0]) + strcpy(workbuffer, boardfilename); + else if (mapList[mapIdx].fileName.IsNotEmpty()) + strcpy(workbuffer, mapList[mapIdx].fileName); - if (currentboardfilename[0]) - { - // only setup art if map differs from previous - if (!previousboardfilename[0] || Bstrcmp(previousboardfilename, currentboardfilename)) - artSetupMapArt(currentboardfilename); - Bstrcpy(previousboardfilename, currentboardfilename); - append_ext_UNSAFE(currentboardfilename, ".mhk"); - engineLoadMHK(currentboardfilename); - } - Bmemcpy(currentboardfilename, boardfilename, BMAX_PATH); + if (workbuffer[0]) + { + // only setup art if map differs from previous + artSetupMapArt(workbuffer); + append_ext_UNSAFE(workbuffer, ".mhk"); + engineLoadMHK(workbuffer); + } if (status == 2) G_NewGame_EnterLevel(); - else if ((status = sv_loadsnapshot(*fil, 0, &h)) || !ReadStatistics() || !SECRET_Load()) // read the rest... + else if ((status = sv_loadsnapshot(*fil, 0, &h))) // read the rest... { // in theory, we could load into an initial dump first and trivially // recover if things go wrong... - Bsprintf(tempbuf, "Loading save game file \"%s\" failed (code %d), cannot recover.", sv.path, status); + Bsprintf(tempbuf, "Loading save game file \"%s\" failed (code %d), cannot recover.", sv->Filename.GetChars(), status); G_GameExit(tempbuf); } @@ -721,50 +537,7 @@ static void G_RestoreTimers(void) ////////// -void G_DeleteSave(savebrief_t const & sv) -{ - if (!sv.isValid()) - return; - - char temp[BMAX_PATH]; - - if (snprintf(temp, sizeof(temp), "%s%s", M_GetSavegamesPath().GetChars(), sv.path)) - { - OSD_Printf("G_SavePlayer: file name \"%s\" too long\n", sv.path); - return; - } - - remove(temp); -} - -void G_DeleteOldSaves(void) -{ - ReadSaveGameHeaders(); - - for (int x = 0; x < g_numinternalsaves; ++x) - { - menusave_t const & msv = g_internalsaves[x]; - if (msv.isOldVer || msv.isUnreadable) - G_DeleteSave(msv.brief); - } -} - -uint16_t G_CountOldSaves(void) -{ - ReadSaveGameHeaders(); - - int bad = 0; - for (int x = 0; x < g_numinternalsaves; ++x) - { - menusave_t const & msv = g_internalsaves[x]; - if (msv.isOldVer || msv.isUnreadable) - ++bad; - } - - return bad; -} - -int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave) +bool G_SavePlayer(FSaveGameNode *sv) { #ifdef __ANDROID__ G_SavePalette(); @@ -780,70 +553,30 @@ int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave) errno = 0; FileWriter *fil; - if (sv.isValid()) + OpenSaveGameForWrite(sv->Filename); + fil = WriteSavegameChunk("snapshot.dat"); + // The above call cannot fail. { - fn.Format("%s%s", M_GetSavegamesPath().GetChars(), sv.path); - OpenSaveGameForWrite(fn); - fil = WriteSavegameChunk("snapshot.dat"); - } - else - { - static char const SaveName[] = "save0000.bsv"; - fn.Format("%s%s", M_GetSavegamesPath().GetChars(), SaveName); - - auto fnp = fn.LockBuffer(); - char* zeros = fnp + (fn.Len() - 8); - fil = savecounter.opennextfile(fnp, zeros); - if (fil) - { - delete fil; - remove(fnp); - OpenSaveGameForWrite(fnp); - fil = WriteSavegameChunk("snapshot.dat"); - } - fn.UnlockBuffer(); - savecounter.count++; - // don't copy the mod dir into sv.path - Bstrcpy(sv.path, fn + (fn.Len() - (ARRAY_SIZE(SaveName) - 1))); - } - - if (!fil) - { - OSD_Printf("G_SavePlayer: failed opening \"%s\" for writing: %s\n", - fn.GetChars(), strerror(errno)); - ready2send = 1; - Net_WaitForServer(); - - G_RestoreTimers(); - ototalclock = totalclock; - return -1; - } - else - { - WriteSavegameChunk("DEMOLITION_ED"); auto& fw = *fil; - sv.isExt = 0; - // temporary hack ud.user_map = G_HaveUserMap(); VM_OnEvent(EVENT_SAVEGAME, g_player[myconnectindex].ps->i, myconnectindex); - portableBackupSave(sv.path, sv.name, ud.last_stateless_volume, ud.last_stateless_level); + portableBackupSave(sv->Filename, sv->SaveTitle, ud.last_stateless_volume, ud.last_stateless_level); // SAVE! - sv_saveandmakesnapshot(fw, sv.name, 0, 0, 0, 0, isAutoSave); - SaveStatistics(); - SECRET_Save(); + sv_saveandmakesnapshot(fw, sv->SaveTitle, 0); + fw.Close(); - FinishSavegameWrite(); + bool res = FinishSavegameWrite(); if (!g_netServer && ud.multimode < 2) { OSD_Printf("Saved: %s\n", fn.GetChars()); - strcpy(apStrings[QUOTE_RESERVED4], "Game Saved"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "Game Saved"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); } @@ -855,39 +588,46 @@ int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave) VM_OnEvent(EVENT_POSTSAVEGAME, g_player[myconnectindex].ps->i, myconnectindex); - return 0; + return res; } } -int32_t G_LoadPlayerMaybeMulti(savebrief_t & sv) + +bool GameInterface::LoadGame(FSaveGameNode *sv) { if (g_netServer || ud.multimode > 1) { - Bstrcpy(apStrings[QUOTE_RESERVED4], "Multiplayer Loading Not Yet Supported"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "Multiplayer Loading Not Yet Supported"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); // g_player[myconnectindex].ps->gm = MODE_GAME; - return 127; + return false; } else { int32_t c = G_LoadPlayer(sv); if (c == 0) g_player[myconnectindex].ps->gm = MODE_GAME; - return c; + return c == 0; } } -void G_SavePlayerMaybeMulti(savebrief_t & sv, bool isAutoSave) +bool GameInterface::SaveGame(FSaveGameNode* sv) { if (g_netServer || ud.multimode > 1) { - Bstrcpy(apStrings[QUOTE_RESERVED4], "Multiplayer Saving Not Yet Supported"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "Multiplayer Saving Not Yet Supported"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); + return false; } else { - G_SavePlayer(sv, isAutoSave); + videoNextPage(); // no idea if this is needed here. + g_screenCapture = 1; + //G_DrawRooms(myconnectindex, 65536); + g_screenCapture = 0; + + return G_SavePlayer(sv); } } @@ -909,11 +649,6 @@ typedef struct dataspec_gv_ intptr_t cnt; } dataspec_gv_t; -#define SV_DEFAULTCOMPRTHRES 8 -static uint8_t savegame_diffcompress; // 0:none, 1:Ken's LZW in cache1d.c -static uint8_t savegame_comprthres; - - #define DS_DYNAMIC 1 // dereference .ptr one more time #define DS_STRING 2 #define DS_CMP 4 @@ -1061,8 +796,8 @@ static int32_t readspecdata(const dataspec_t *spec, FileReader *fil, uint8_t **d if (ksiz != siz) { OSD_Printf("rsd: spec=%s, idx=%d, mem=%p\n", (char *)sptr->ptr, (int32_t)(spec - sptr), mem); - OSD_Printf(" (%s): read %d, expected %d!\n", - ((spec->flags & DS_CNTMASK) == 0 && spec->size * cnt <= savegame_comprthres) ? "uncompressed" : "compressed", ksiz, siz); + OSD_Printf(" : read %d, expected %d!\n", + ksiz, siz); if (ksiz == -1) OSD_Printf(" read: %s\n", strerror(errno)); @@ -1364,9 +1099,6 @@ static void sv_create_lua_state(void) static void sv_postactordata(); static void sv_preanimateptrsave(); static void sv_postanimateptr(); -static void sv_prequote(); -static void sv_quotesave(); -static void sv_quoteload(); static void sv_prequoteredef(); static void sv_quoteredefsave(); static void sv_quoteredefload(); @@ -1386,9 +1118,6 @@ static int32_t savegame_projectilecnt = 0; ((sizeof(g_player[0].user_name)+sizeof(g_player[0].pcolor)+sizeof(g_player[0].pteam) \ +sizeof(g_player[0].frags)+sizeof(DukePlayer_t))*MAXPLAYERS) -static uint8_t savegame_quotedef[MAXQUOTES >> 3]; -static char (*savegame_quotes)[MAXQUOTELEN]; -static char (*savegame_quoteredefs)[MAXQUOTELEN]; static uint8_t savegame_restdata[SVARDATALEN]; static char svgm_udnetw_string [] = "blK:udnt"; @@ -1421,8 +1150,6 @@ static const dataspec_t svgm_udnetw[] = { DS_NOCHK, &ud.noexits, sizeof(ud.noexits), 1 }, { DS_NOCHK, &ud.playerai, sizeof(ud.playerai), 1 }, { 0, &ud.pause_on, sizeof(ud.pause_on), 1 }, - { DS_NOCHK, ¤tboardfilename[0], BMAX_PATH, 1 }, -// { DS_LOADFN, (void *)&sv_postudload, 0, 1 }, { 0, connectpoint2, sizeof(connectpoint2), 1 }, { 0, &randomseed, sizeof(randomseed), 1 }, { 0, &g_globalRandom, sizeof(g_globalRandom), 1 }, @@ -1528,20 +1255,6 @@ static const dataspec_t svgm_anmisc[] = { 0, &g_pskyidx, sizeof(g_pskyidx), 1 }, // DS_NOCHK? { 0, &g_earthquakeTime, sizeof(g_earthquakeTime), 1 }, - { DS_SAVEFN|DS_LOADFN|DS_NOCHK, (void *)sv_prequote, 0, 1 }, - { DS_SAVEFN, (void *)&sv_quotesave, 0, 1 }, - { DS_NOCHK, &savegame_quotedef, sizeof(savegame_quotedef), 1 }, // quotes can change during runtime, but new quote numbers cannot be allocated - { DS_DYNAMIC, &savegame_quotes, MAXQUOTELEN, MAXQUOTES }, - { DS_LOADFN, (void *)&sv_quoteload, 0, 1 }, - - { DS_NOCHK|DS_SAVEFN|DS_LOADFN, (void *)&sv_prequoteredef, 0, 1 }, - { DS_NOCHK|DS_SAVEFN, (void *)&sv_quoteredefsave, 0, 1 }, // quote redefinitions replace quotes at runtime, but cannot be changed after CON compilation - { DS_NOCHK|DS_DYNAMIC|DS_CNT(g_numXStrings), &savegame_quoteredefs, MAXQUOTELEN, (intptr_t)&g_numXStrings }, - { DS_NOCHK|DS_LOADFN, (void *)&sv_quoteredefload, 0, 1 }, - { DS_NOCHK|DS_SAVEFN|DS_LOADFN, (void *)&sv_postquoteredef, 0, 1 }, -#ifdef LUNATIC - { 0, g_playerWeapon, sizeof(weapondata_t), MAXPLAYERS*MAX_WEAPONS }, -#endif { DS_SAVEFN, (void *)&sv_restsave, 0, 1 }, { 0, savegame_restdata, 1, sizeof(savegame_restdata) }, // sz/cnt swapped for kdfread { DS_LOADFN, (void *)&sv_restload, 0, 1 }, @@ -1655,14 +1368,10 @@ static void SV_AllocSnap(int32_t allocinit) } // make snapshot only if spot < 0 (demo) -int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress, bool isAutoSave) +int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot) { savehead_t h; - // set a few savegame system globals - savegame_comprthres = SV_DEFAULTCOMPRTHRES; - savegame_diffcompress = diffcompress; - // calculate total snapshot size #if !defined LUNATIC sv_makevarspec(); @@ -1678,17 +1387,9 @@ int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, i h.majorver = SV_MAJOR_VER; h.minorver = SV_MINOR_VER; h.ptrsize = sizeof(intptr_t); - - if (isAutoSave) - h.ptrsize |= 1u << 7u; - h.bytever = BYTEVERSION; h.userbytever = ud.userbytever; h.scriptcrc = g_scriptcrc; - h.comprthres = savegame_comprthres; - h.recdiffsp = recdiffsp; - h.diffcompress = savegame_diffcompress; - h.synccompress = synccompress; h.reccnt = 0; h.snapsiz = svsnapsiz; @@ -1701,40 +1402,33 @@ int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, i h.levnum = ud.level_number; h.skill = ud.player_skill; - const uint32_t BSZ = sizeof(h.boardfn); - EDUKE32_STATIC_ASSERT(BSZ == sizeof(currentboardfilename)); - Bstrncpy(h.boardfn, currentboardfilename, BSZ); - if (spot >= 0) { // savegame - Bstrncpyz(h.savename, name, sizeof(h.savename)); auto fw = WriteSavegameChunk("header.dat"); fw->Write(&h, sizeof(savehead_t)); + + G_WriteSaveHeader(name); } else { - // demo - + // demo (currently broken, needs a new format.) const time_t t = time(NULL); - struct tm * st; - - Bstrncpyz(h.savename, "EDuke32 demo", sizeof(h.savename)); - if (t>=0 && (st = localtime(&t))) - Bsnprintf(h.savename, sizeof(h.savename), "Demo %04d%02d%02d %s", - st->tm_year+1900, st->tm_mon+1, st->tm_mday, GetGitDescription()); + struct tm * st = localtime(&t); + FStringf demoname("Demo %04d%02d%02d %s", st->tm_year+1900, st->tm_mon+1, st->tm_mday, GetGitDescription()); fil.Write(&h, sizeof(savehead_t)); } // write header - +#if 0 // not usable anymore if (spot >= 0 && tileData(TILE_SAVESHOT)) { auto fw = WriteSavegameChunk("screenshot.dat"); fw->Write(tileData(TILE_SAVESHOT), 320*200); } +#endif if (spot >= 0) @@ -1847,8 +1541,6 @@ int32_t sv_loadsnapshot(FileReader &fil, int32_t spot, savehead_t *h) OSD_Printf("sv_loadsnapshot: snapshot size: %d bytes.\n", h->snapsiz); #endif - savegame_comprthres = h->comprthres; - if (spot >= 0) { // savegame @@ -1861,9 +1553,6 @@ int32_t sv_loadsnapshot(FileReader &fil, int32_t spot, savehead_t *h) } else { - // demo - savegame_diffcompress = h->diffcompress; - svsnapsiz = h->snapsiz; SV_AllocSnap(1); @@ -1956,7 +1645,6 @@ int32_t sv_readdiff(FileReader &fil) // SVGM data description static void sv_postudload() { -// Bmemcpy(&boardfilename[0], ¤tboardfilename[0], BMAX_PATH); // DON'T do this in demos! #if 1 m_level_number = ud.level_number; ud.m_volume_number = ud.volume_number; @@ -2018,34 +1706,6 @@ static void sv_postanimateptr() { G_Util_PtrToIdx(g_animatePtr, g_animateCnt, sector, P2I_BACK); } -static void sv_prequote() -{ - if (!savegame_quotes) - { - void *ptr = Xcalloc(MAXQUOTES, MAXQUOTELEN); - savegame_quotes = (char(*)[MAXQUOTELEN])ptr; - } -} -static void sv_quotesave() -{ - Bmemset(savegame_quotedef, 0, sizeof(savegame_quotedef)); - for (int i = 0; i < MAXQUOTES; i++) - if (apStrings[i]) - { - savegame_quotedef[i>>3] |= 1<<(i&7); - Bmemcpy(savegame_quotes[i], apStrings[i], MAXQUOTELEN); - } -} -static void sv_quoteload() -{ - for (int i = 0; i < MAXQUOTES; i++) - if (savegame_quotedef[i>>3] & pow2char[i&7]) - { - C_AllocQuote(i); - Bmemcpy(apStrings[i], savegame_quotes[i], MAXQUOTELEN); - } -} - static void sv_preprojectilesave() { savegame_projectilecnt = 0; @@ -2101,31 +1761,6 @@ static void sv_postprojectileload() DO_FREE_AND_NULL(savegame_projectiledata); } -static void sv_prequoteredef() -{ - // "+1" needed for dfwrite which doesn't handle the src==NULL && cnt==0 case - void *ptr = Xcalloc(g_numXStrings+1, MAXQUOTELEN); - savegame_quoteredefs = (decltype(savegame_quoteredefs))ptr; -} -static void sv_quoteredefsave() -{ - for (int i = 0; i < g_numXStrings; i++) - if (apXStrings[i]) - Bmemcpy(savegame_quoteredefs[i], apXStrings[i], MAXQUOTELEN); -} -static void sv_quoteredefload() -{ - for (int i = 0; i < g_numXStrings; i++) - { - if (!apXStrings[i]) - apXStrings[i] = (char *)Xcalloc(1,MAXQUOTELEN); - Bmemcpy(apXStrings[i], savegame_quoteredefs[i], MAXQUOTELEN); - } -} -static void sv_postquoteredef() -{ - Xfree(savegame_quoteredefs), savegame_quoteredefs=NULL; -} static void sv_restsave() { uint8_t * mem = savegame_restdata; @@ -2294,29 +1929,10 @@ static void postloadplayer(int32_t savegamep) //2.5 if (savegamep) { - int32_t musicIdx = (ud.music_episode*MAXLEVELS) + ud.music_level; - - Bmemset(gotpic, 0, sizeof(gotpic)); + Bmemset(gotpic, 0, sizeof(gotpic)); S_ClearSoundLocks(); G_CacheMapData(); - - if (boardfilename[0] != 0 && ud.level_number == 7 && ud.volume_number == 0 && ud.music_level == USERMAPMUSICFAKELEVEL && ud.music_episode == USERMAPMUSICFAKEVOLUME) - { - char levname[BMAX_PATH]; - G_SetupFilenameBasedMusic(levname, boardfilename); - } - - if (g_mapInfo[musicIdx].musicfn != NULL && (musicIdx != g_musicIndex || different_user_map)) - { - ud.music_episode = g_musicIndex / MAXLEVELS; - ud.music_level = g_musicIndex % MAXLEVELS; - S_PlayLevelMusicOrNothing(musicIdx); - } - else - S_ContinueLevelMusic(); - - if (MusicEnabled()) - S_PauseMusic(false); + MUS_ResumeSaved(); g_player[myconnectindex].ps->gm = MODE_GAME; ud.recstat = 0; diff --git a/source/duke3d/src/savegame.h b/source/duke3d/src/savegame.h index d66e837f9..08f8d7213 100644 --- a/source/duke3d/src/savegame.h +++ b/source/duke3d/src/savegame.h @@ -46,93 +46,32 @@ typedef struct uint32_t userbytever; uint32_t scriptcrc; - uint8_t comprthres; - uint8_t recdiffsp, diffcompress, synccompress; + uint8_t recdiffsp; // 4 bytes int32_t reccnt, snapsiz; // 8 bytes - char savename[MAXSAVEGAMENAMESTRUCT]; uint8_t numplayers, volnum, levnum, skill; - char boardfn[BMAX_PATH]; // 286 bytes -#ifdef __ANDROID__ - char skillname[32], volname[32]; -#endif - uint8_t getPtrSize() const { return ptrsize & 0x7Fu; } - bool isAutoSave() const { return !!(ptrsize & (1u<<7u)); } + uint8_t getPtrSize() const { return ptrsize; } } savehead_t; #pragma pack(pop) -struct savebrief_t -{ - savebrief_t() - { - reset(); - } - savebrief_t(char const *n) - { - strncpy(name, n, MAXSAVEGAMENAME); - path[0] = '\0'; - } - - char name[MAXSAVEGAMENAMESTRUCT]; - char path[BMAX_PATH]; - uint8_t isExt = 0; - - void reset() - { - name[0] = '\0'; - path[0] = '\0'; - isExt = 0; - } - bool isValid() const - { - return path[0] != '\0'; - } -}; - -struct menusave_t -{ - savebrief_t brief; - uint8_t isOldVer = 0; - uint8_t isUnreadable = 0; - uint8_t isAutoSave = 0; - void clear() - { - brief.reset(); - isOldVer = 0; - isUnreadable = 0; - isAutoSave = 0; - } -}; - -extern savebrief_t g_lastautosave, g_lastusersave, g_freshload; -extern int32_t g_lastAutoSaveArbitraryID; +extern int32_t g_fakeSaveID; extern bool g_saveRequested; -extern savebrief_t * g_quickload; -extern menusave_t * g_menusaves; -extern uint16_t g_nummenusaves; int32_t sv_updatestate(int32_t frominit); int32_t sv_readdiff(FileReader& fil); uint32_t sv_writediff(FileWriter *fil); int32_t sv_loadheader(FileReader &fil, int32_t spot, savehead_t *h); int32_t sv_loadsnapshot(FileReader &fil, int32_t spot, savehead_t *h); -int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress, bool isAutoSave = false); +int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot); void sv_freemem(); -void G_DeleteSave(savebrief_t const & sv); -void G_DeleteOldSaves(void); -uint16_t G_CountOldSaves(void); -int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave); -int32_t G_LoadPlayer(savebrief_t & sv); int32_t G_LoadSaveHeaderNew(char const *fn, savehead_t *saveh); void ReadSaveGameHeaders(void); -void G_SavePlayerMaybeMulti(savebrief_t & sv, bool isAutoSave = false); -int32_t G_LoadPlayerMaybeMulti(savebrief_t & sv); #ifdef YAX_ENABLE extern void sv_postyaxload(void); diff --git a/source/duke3d/src/sbar.cpp b/source/duke3d/src/sbar.cpp index 9c5043a49..4fec52794 100644 --- a/source/duke3d/src/sbar.cpp +++ b/source/duke3d/src/sbar.cpp @@ -770,13 +770,13 @@ void G_DrawStatusBar(int32_t snum) if (!WW2GI) { if (j > 0) - minitext(288-30-o, 180, "On", 0, orient); + minitext(288-30-o, 180, GStrings("OPTVAL_ON"), 0, orient); else if ((uint32_t) j != 0x80000000) - minitext(284-30-o, 180, "Off", 2, orient); + minitext(284-30-o, 180, GStrings("OPTVAL_OFF"), 2, orient); } if (p->inven_icon >= ICON_SCUBA) - minitext(284-35-o, 180, "Auto", 2, orient); + minitext(284-35-o, 180, GStrings("OPTVAL_AUTO"), 2, orient); minitext_yofs = 0; } @@ -1000,15 +1000,15 @@ void G_DrawStatusBar(int32_t snum) // XXX: i < 0? rotatesprite_fs(sbarx(231-o), sbary(SBY+13), sb16, 0, i, 0, 0, 10+16+permbit); minitext(292-30-o, SBY+24, "%", 6, 10+16+permbit + ROTATESPRITE_MAX); - if (p->inven_icon >= ICON_SCUBA) minitext(284-35-o, SBY+14, "Auto", 2, 10+16+permbit + ROTATESPRITE_MAX); + if (p->inven_icon >= ICON_SCUBA) minitext(284-35-o, SBY+14, GStrings("OPTVAL_AUTO"), 2, 10+16+permbit + ROTATESPRITE_MAX); } if (u&(2048+4096) && !WW2GI) { j = G_GetInvOn(p); - if (j > 0) minitext(288-30-o, SBY+14, "On", 0, 10+16+permbit + ROTATESPRITE_MAX); - else if ((uint32_t) j != 0x80000000) minitext(284-30-o, SBY+14, "Off", 2, 10+16+permbit + ROTATESPRITE_MAX); + if (j > 0) minitext(288-30-o, SBY+14, GStrings("OPTVAL_ON"), 0, 10+16+permbit + ROTATESPRITE_MAX); + else if ((uint32_t) j != 0x80000000) minitext(284-30-o, SBY+14, GStrings("OPTVAL_OFF"), 2, 10+16+permbit + ROTATESPRITE_MAX); } if (u&8192) diff --git a/source/duke3d/src/screens.cpp b/source/duke3d/src/screens.cpp index 19c4578a7..8be60fbb5 100644 --- a/source/duke3d/src/screens.cpp +++ b/source/duke3d/src/screens.cpp @@ -32,6 +32,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sbar.h" #include "screens.h" #include "gamecvars.h" +#include "menu/menu.h" +#include "mapinfo.h" BEGIN_DUKE_NS @@ -181,14 +183,14 @@ static void G_ShowScores(void) if (g_mostConcurrentPlayers > 1 && (g_gametypeFlags[ud.coop]&GAMETYPE_SCORESHEET)) { - gametext_center(SCORESHEETOFFSET+58+2, "Multiplayer Totals"); - gametext_center(SCORESHEETOFFSET+58+10, g_mapInfo[G_LastMapInfoIndex()].name); + gametext_center(SCORESHEETOFFSET+58+2, GStrings("Multiplayer Totals")); + gametext_center(SCORESHEETOFFSET+58+10, currentLevel->DisplayName()); t = 0; - minitext(70, SCORESHEETOFFSET+80, "Name", 8, 2+8+16+ROTATESPRITE_MAX); - minitext(170, SCORESHEETOFFSET+80, "Frags", 8, 2+8+16+ROTATESPRITE_MAX); - minitext(200, SCORESHEETOFFSET+80, "Deaths", 8, 2+8+16+ROTATESPRITE_MAX); - minitext(235, SCORESHEETOFFSET+80, "Ping", 8, 2+8+16+ROTATESPRITE_MAX); + minitext(70, SCORESHEETOFFSET+80, GStrings("Name"), 8, 2+8+16+ROTATESPRITE_MAX); + minitext(170, SCORESHEETOFFSET+80, GStrings("Frags"), 8, 2+8+16+ROTATESPRITE_MAX); + minitext(200, SCORESHEETOFFSET+80, GStrings("Deaths"), 8, 2+8+16+ROTATESPRITE_MAX); + minitext(235, SCORESHEETOFFSET+80, GStrings("Ping"), 8, 2+8+16+ROTATESPRITE_MAX); for (i=g_mostConcurrentPlayers-1; i>=0; i--) { @@ -957,11 +959,10 @@ void G_DisplayRest(int32_t smoothratio) if (textret == 0 && ud.overhead_on == 2) { const int32_t a = (ud.screen_size > 0) ? 147 : 179; - char const * levelname = g_mapInfo[ud.volume_number*MAXLEVELS + ud.level_number].name; - if (G_HaveUserMap()) - levelname = boardfilename; - else if (!(G_GetLogoFlags() & LOGO_HIDEEPISODE)) - minitext(5, a+6, g_volumeNames[ud.volume_number], 0, 2+8+16+256); + char const * levelname = currentLevel->DisplayName(); + + if (!Menu_HaveUserMap() && !(G_GetLogoFlags() & LOGO_HIDEEPISODE)) + minitext(5, a+6, GStrings.localize(gVolumeNames[ud.volume_number]), 0, 2+8+16+256); minitext(5, a+6+6, levelname, 0, 2+8+16+256); } } @@ -983,7 +984,7 @@ void G_DisplayRest(int32_t smoothratio) G_PrintGameQuotes(screenpeek); - if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1) + if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1 && !M_Active()) { int32_t o = 10|16; @@ -991,47 +992,8 @@ void G_DisplayRest(int32_t smoothratio) o |= 1|32; else if (g_levelTextTime < 5) o |= 1; - - if (g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name != NULL) - { - char const * const fn = currentboardfilename[0] != 0 && - ud.volume_number == 0 && ud.level_number == 7 - ? currentboardfilename - : g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name; - - menutext_(160<<16, (90+16+8)<<16, -g_levelTextTime+22/*quotepulseshade*/, fn, o, TEXT_XCENTER); - } - } - - if (I_EscapeTrigger() && ud.overhead_on == 0 - && ud.show_help == 0 - && g_player[myconnectindex].ps->newowner == -1) - { - if ((g_player[myconnectindex].ps->gm&MODE_MENU) == MODE_MENU && g_currentMenu <= MENU_MAIN_INGAME) - { - I_EscapeTriggerClear(); - S_PlaySound(EXITMENUSOUND); - Menu_Change(MENU_CLOSE); - if (!ud.pause_on) - S_PauseSounds(false); - } - else if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU && - g_player[myconnectindex].ps->newowner == -1 && - (g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE) - { - I_EscapeTriggerClear(); - S_PauseSounds(true); - - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) ready2send = 0; - - if (g_player[myconnectindex].ps->gm&MODE_GAME) Menu_Change(MENU_MAIN_INGAME); - else Menu_Change(MENU_MAIN); - screenpeek = myconnectindex; - - S_MenuSound(); - } + + menutext_(160<<16, (90+16+8)<<16, -g_levelTextTime+22/*quotepulseshade*/, currentLevel->DisplayName(), o, TEXT_XCENTER); } if (g_player[myconnectindex].ps->newowner == -1 && ud.overhead_on == 0 && cl_crosshair && ud.camerasprite == -1) @@ -1073,7 +1035,7 @@ void G_DisplayRest(int32_t smoothratio) } if (ud.pause_on==1 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0) - menutext_center(100, "Game Paused"); + menutext_center(100, GStrings("Game Paused")); if (cl_showcoords) G_PrintCoords(screenpeek); @@ -1132,7 +1094,7 @@ void G_DisplayRest(int32_t smoothratio) { Bsprintf(tempbuf, "%s^00 has called a vote for map", g_player[voting].user_name); gametext_center(40, tempbuf); - Bsprintf(tempbuf, "%s (E%dL%d)", g_mapInfo[vote_episode*MAXLEVELS + vote_map].name, vote_episode+1, vote_map+1); + Bsprintf(tempbuf, "%s (E%dL%d)", mapList[vote_episode*MAXLEVELS + vote_map].DisplayName(), vote_episode+1, vote_map+1); gametext_center(48, tempbuf); gametext_center(70, "Press F1 to Accept, F2 to Decline"); } @@ -1157,8 +1119,8 @@ void G_DisplayRest(int32_t smoothratio) { if (g_player[myconnectindex].ps->gm&MODE_TYPE) Net_SendMessage(); - else - M_DisplayMenus(); + //else + //M_DisplayMenus(); } { @@ -1183,7 +1145,7 @@ void G_DisplayRest(int32_t smoothratio) GameStats GameInterface::getStats() { DukePlayer_t* p = g_player[myconnectindex].ps; - return { p->actors_killed, p->max_actors_killed, p->secret_rooms, p->max_secret_rooms, p->player_par / REALGAMETICSPERSEC }; + return { p->actors_killed, p->max_actors_killed, p->secret_rooms, p->max_secret_rooms, p->player_par / REALGAMETICSPERSEC, p->frag }; } @@ -1317,7 +1279,7 @@ void gameDisplaySharewareScreens() void G_DisplayExtraScreens(void) { - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); if (!DUKEBETA && (!VOLUMEALL || G_GetLogoFlags() & LOGO_SHAREWARESCREENS)) @@ -1333,7 +1295,7 @@ void gameDisplay3DRScreen() { Net_GetPackets(); - if (testkopen("3dr.ivf", 0) || testkopen("3dr.anm", 0)) + if (fileSystem.FileExists("3dr.ivf") || fileSystem.FileExists("3dr.anm")) { Anim_Play("3dr.anm"); G_FadePalette(0, 0, 0, 252); @@ -1497,7 +1459,7 @@ void G_DisplayLogo(void) renderFlushPerms(); videoNextPage(); - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); // JBF 20031228 S_ClearSoundLocks(); // JBF 20031228 @@ -1699,7 +1661,7 @@ static void G_BonusCutscenes(void) fadepal(0, 0, 0, 0, 252, 4); VOL1_END: - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); S_ClearSoundLocks(); break; @@ -1710,7 +1672,7 @@ static void G_BonusCutscenes(void) videoSetViewableArea(0, 0, xdim-1, ydim-1); - S_StopMusic(); + Mus_Stop(); videoClearScreen(0L); videoNextPage(); @@ -1744,7 +1706,7 @@ static void G_BonusCutscenes(void) videoSetViewableArea(0, 0, xdim-1, ydim-1); - S_StopMusic(); + Mus_Stop(); videoClearScreen(0L); videoNextPage(); @@ -1786,11 +1748,11 @@ static void G_BonusCutscenes(void) P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1); // JBF 20040308 // G_FadePalette(0,0,0,252); videoClearScreen(0L); - menutext_center(60, "Thanks to all our"); - menutext_center(60+16, "fans for giving"); - menutext_center(60+16+16, "us big heads."); - menutext_center(70+16+16+16, "Look for a Duke Nukem 3D"); - menutext_center(70+16+16+16+16, "sequel soon."); + menutext_center(60, GStrings("Thanks to all our")); + menutext_center(60+16, GStrings("fans for giving")); + menutext_center(60+16+16, GStrings("us big heads.")); + menutext_center(70+16+16+16, GStrings("Look for a Duke Nukem 3D")); + menutext_center(70+16+16+16+16, GStrings("sequel soon.")); videoNextPage(); fadepal(0, 0, 0, 252, 0, -12); @@ -1826,7 +1788,7 @@ static void G_BonusCutscenes(void) if ((G_GetLogoFlags() & LOGO_NOE3BONUSSCENE) && (G_GetLogoFlags() & LOGO_NOE3RADLOGO) && (PLUTOPAK || (G_GetLogoFlags() & LOGO_NODUKETEAMPIC))) return; - S_StopMusic(); + Mus_Stop(); videoClearScreen(0L); videoNextPage(); if (adult_lockout == 0 && !(G_GetLogoFlags() & LOGO_NOE3BONUSSCENE)) @@ -1912,13 +1874,13 @@ static void G_DisplayMPResultsScreen(void) rotatesprite_fs(160<<16, 34<<16, 65536L, 0, INGAMEDUKETHREEDEE, 0, 0, 10); if (PLUTOPAK) // JBF 20030804 rotatesprite_fs((260)<<16, 36<<16, 65536L, 0, PLUTOPAKSPRITE+2, 0, 0, 2+8); - gametext_center(58+2, "Multiplayer Totals"); - gametext_center(58+10, g_mapInfo[G_LastMapInfoIndex()].name); + gametext_center(58+2, GStrings("Multiplayer Totals")); + gametext_center(58+10, currentLevel->DisplayName()); - gametext_center_shade(165, "Press any key or button to continue", quotepulseshade); + gametext_center_shade(165, GStrings("Presskey"), quotepulseshade); - minitext(38, 80, "Name", 8, 2+8+16+128); - minitext(269, 80, "Kills", 8, 2+8+16+128); + minitext(38, 80, GStrings("Name"), 8, 2+8+16+128); + minitext(269, 80, GStrings("Kills"), 8, 2+8+16+128); for (i=0; i9; ii/=10, ij++) { } + for (ii=currentLevel->parTime/(60), ij=1; ii>9; ii/=10, ij++) { } clockpad = max(clockpad, ij); - if (!NAM_WW2GI && g_mapInfo[G_LastMapInfoIndex()].designertime) + if (!NAM_WW2GI && currentLevel->designerTime) { - for (ii=g_mapInfo[G_LastMapInfoIndex()].designertime/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { } + for (ii= currentLevel->designerTime/(60), ij=1; ii>9; ii/=10, ij++) { } clockpad = max(clockpad, ij); } } @@ -2014,13 +1976,13 @@ const char* G_PrintParTime(void) { if (ud.last_level < 1) return ""; - return G_PrintTime2(g_mapInfo[G_LastMapInfoIndex()].partime); + return G_PrintTime2(currentLevel->parTime*REALGAMETICSPERSEC); } const char* G_PrintDesignerTime(void) { if (ud.last_level < 1) return ""; - return G_PrintTime2(g_mapInfo[G_LastMapInfoIndex()].designertime); + return G_PrintTime2(currentLevel->designerTime*REALGAMETICSPERSEC); } const char* G_PrintBestTime(void) { @@ -2032,7 +1994,7 @@ void G_BonusScreen(int32_t bonusonly) int32_t gfx_offset; int32_t bonuscnt; int32_t clockpad = 2; - char *lastmapname; + const char *lastmapname; if (g_networkMode == NET_DEDICATED_SERVER) return; @@ -2045,9 +2007,9 @@ void G_BonusScreen(int32_t bonusonly) } else { - lastmapname = g_mapInfo[G_LastMapInfoIndex()].name; - if (!lastmapname) // this isn't right but it's better than no name at all - lastmapname = g_mapInfo[G_LastMapInfoIndex()].name; + lastmapname = currentLevel->name; + if (!lastmapname || !*lastmapname) // this isn't right but it's better than no name at all + lastmapname = currentLevel->fileName; } @@ -2073,7 +2035,7 @@ void G_BonusScreen(int32_t bonusonly) totalclock = 0; bonuscnt = 0; - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); S_ClearSoundLocks(); @@ -2119,9 +2081,9 @@ void G_BonusScreen(int32_t bonusonly) if (lastmapname) menutext_center(20-6, lastmapname); - menutext_center(36-6, "Completed"); + menutext_center(36-6, GStrings("Completed")); - gametext_center_shade(192, "Press any key or button to continue", quotepulseshade); + gametext_center_shade(192, GStrings("PRESSKEY"), quotepulseshade); if (MusicEnabled()) S_PlaySound(BONUSMUSIC); @@ -2200,35 +2162,35 @@ void G_BonusScreen(int32_t bonusonly) if (lastmapname) menutext_center(20-6, lastmapname); - menutext_center(36-6, "Completed"); + menutext_center(36-6, GStrings("Completed")); - gametext_center_shade(192, "Press any key or button to continue", quotepulseshade); + gametext_center_shade(192, GStrings("PRESSKEY"), quotepulseshade); if (totalclock > (60*3)) { yy = zz = 59; - gametext(10, yy+9, "Your Time:"); + gametext(10, yy+9, GStrings("TXT_YourTime")); yy+=10; if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0])) { - if (g_mapInfo[G_LastMapInfoIndex()].partime) + if (currentLevel->parTime) { - gametext(10, yy+9, "Par Time:"); + gametext(10, yy+9, GStrings("TXT_ParTime")); yy+=10; } - if (!NAM_WW2GI && !DUKEBETA && g_mapInfo[G_LastMapInfoIndex()].designertime) + if (!NAM_WW2GI && !DUKEBETA && currentLevel->designerTime) { // EDuke 2.0 / NAM source suggests "Green Beret's Time:" - gametext(10, yy+9, "3D Realms' Time:"); + gametext(10, yy+9, GStrings("TXT_3DRTIME")); yy+=10; } } if (ud.playerbest > 0) { - gametext(10, yy+9, (g_player[myconnectindex].ps->player_par > 0 && g_player[myconnectindex].ps->player_par < ud.playerbest) ? "Prev Best Time:" : "Your Best Time:"); + gametext(10, yy+9, (g_player[myconnectindex].ps->player_par > 0 && g_player[myconnectindex].ps->player_par < ud.playerbest) ? GStrings("TXT_PREVBEST") : GStrings("TXT_YourBest")); yy += 10; } @@ -2249,21 +2211,21 @@ void G_BonusScreen(int32_t bonusonly) G_PrintYourTime(); gametext_number((320>>2)+71, yy+9, tempbuf); if (g_player[myconnectindex].ps->player_par < ud.playerbest) - gametext((320>>2)+89+(clockpad*24), yy+9, "New record!"); + gametext((320>>2)+89+(clockpad*24), yy+9, GStrings("TXT_NEWRECORD")); } else - gametext_pal((320>>2)+71, yy+9, "Cheated!", 2); + gametext_pal((320>>2)+71, yy+9, GStrings("TXT_Cheated"), 2); yy+=10; if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0])) { - if (g_mapInfo[G_LastMapInfoIndex()].partime) + if (currentLevel->parTime) { G_PrintParTime(); gametext_number((320>>2)+71, yy+9, tempbuf); yy+=10; } - if (!NAM_WW2GI && !DUKEBETA && g_mapInfo[G_LastMapInfoIndex()].designertime) + if (!NAM_WW2GI && !DUKEBETA && currentLevel->designerTime) { G_PrintDesignerTime(); gametext_number((320>>2)+71, yy+9, tempbuf); @@ -2283,9 +2245,9 @@ void G_BonusScreen(int32_t bonusonly) zz = yy += 5; if (totalclock > (60*6)) { - gametext(10, yy+9, "Enemies Killed:"); + gametext(10, yy+9, GStrings("TXT_EnemiesKilled")); yy += 10; - gametext(10, yy+9, "Enemies Left:"); + gametext(10, yy+9, GStrings("TXT_EnemiesLeft")); yy += 10; if (bonuscnt == 2) @@ -2308,7 +2270,7 @@ void G_BonusScreen(int32_t bonusonly) yy += 10; if (ud.player_skill > 3) { - gametext((320>>2)+70, yy+9, "N/A"); + gametext((320>>2)+70, yy+9, GStrings("TXT_N_A")); yy += 10; } else @@ -2325,9 +2287,9 @@ void G_BonusScreen(int32_t bonusonly) zz = yy += 5; if (totalclock > (60*9)) { - gametext(10, yy+9, "Secrets Found:"); + gametext(10, yy+9, GStrings("TXT_SECFND")); yy += 10; - gametext(10, yy+9, "Secrets Missed:"); + gametext(10, yy+9, GStrings("TXT_SECMISS")); yy += 10; if (bonuscnt == 4) bonuscnt++; diff --git a/source/duke3d/src/screens.h b/source/duke3d/src/screens.h index beea34478..8c4ad1fc1 100644 --- a/source/duke3d/src/screens.h +++ b/source/duke3d/src/screens.h @@ -26,12 +26,6 @@ extern void G_DisplayExtraScreens(void); extern void G_DisplayLogo(void); extern void G_DoOrderScreen(void); -static inline int G_LastMapInfoIndex(void) -{ - Bassert(ud.last_level >= 1); // NOTE: last_level is 1-based - return ud.volume_number*MAXLEVELS + ud.last_level-1; -} - #ifdef DEBUGGINGAIDS typedef struct { uint32_t lastgtic; diff --git a/source/duke3d/src/screentext.cpp b/source/duke3d/src/screentext.cpp index 9329c52e3..792d70d89 100644 --- a/source/duke3d/src/screentext.cpp +++ b/source/duke3d/src/screentext.cpp @@ -26,7 +26,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "sbar.h" #include "menus.h" +#include "gstrings.h" +#include "quotemgr.h" +#include "c_dispatch.h" BEGIN_DUKE_NS // get the string length until the next '\n' @@ -986,16 +989,20 @@ void G_AddUserQuote(const char *daquote) { int32_t i; - for (i=MAXUSERQUOTES-1; i>0; i--) - { - Bstrcpy(user_quote[i], user_quote[i-1]); - user_quote_time[i] = user_quote_time[i-1]; - } - Bstrcpy(user_quote[0], daquote); - OSD_Printf("%s\n", daquote); + if (hud_messages == 0) return; + Printf(PRINT_MEDIUM | PRINT_NOTIFY, "%s\n", daquote); + if (hud_messages == 1) + { + for (i = MAXUSERQUOTES - 1; i > 0; i--) + { + Bstrcpy(user_quote[i], user_quote[i - 1]); + user_quote_time[i] = user_quote_time[i - 1]; + } + Bstrcpy(user_quote[0], daquote); - user_quote_time[0] = hud_messagetime; - pub = NUMPAGES; + user_quote_time[0] = hud_messagetime; + pub = NUMPAGES; + } } int32_t textsc(int32_t sc) @@ -1004,6 +1011,7 @@ int32_t textsc(int32_t sc) } + #define FTAOPAQUETIME 30 // alpha increments of 8 --> 256 / 8 = 32 --> round up to power of 2 --> 32 --> divide by 2 --> 16 alphatabs required @@ -1048,6 +1056,8 @@ static FORCE_INLINE int32_t text_ypos(void) #endif } +static FString text_quote; // To put text into the quote display that does not come from the quote array. (Is it really necessary to implement everything as a hack??? :( ) + // this handles both multiplayer and item pickup message type text // both are passed on to gametext void G_PrintGameQuotes(int32_t snum) @@ -1068,12 +1078,6 @@ void G_PrintGameQuotes(int32_t snum) if (k <= 1) break; - if (EDUKE32_PREDICT_FALSE(apStrings[ps->ftq] == NULL)) - { - OSD_Printf(OSD_ERROR "%s %d null quote %d\n", "screentext:", __LINE__, ps->ftq); - break; - } - int32_t y = ybase; if (reserved_quote) { @@ -1103,7 +1107,8 @@ void G_PrintGameQuotes(int32_t snum) } #endif - height = gametext_(x, y, apStrings[ps->ftq], textsh(k), pal, texto(k), texta(k), TEXT_XCENTER).y + (1<<16); + if (text_quote.IsNotEmpty() && ps->ftq == -32768) height = gametext_(x, y, text_quote, textsh(k), pal, texto(k), texta(k), TEXT_XCENTER).y + (1 << 16); + else height = gametext_(x, y, quoteMgr.GetQuote(ps->ftq), textsh(k), pal, texto(k), texta(k), TEXT_XCENTER).y + (1<<16); } while (0); @@ -1142,26 +1147,50 @@ void P_DoQuote(int32_t q, DukePlayer_t *p) q &= ~MAXQUOTES; } - if (EDUKE32_PREDICT_FALSE(apStrings[q] == NULL)) - { - OSD_Printf(OSD_ERROR "%s %d null quote %d\n", "screentext:", __LINE__, q); - return; - } - if (p->fta > 0 && q != QUOTE_RESERVED && q != QUOTE_RESERVED2) if (p->ftq == QUOTE_RESERVED || p->ftq == QUOTE_RESERVED2) return; - p->fta = 100; - if (p->ftq != q) { - if (p == g_player[screenpeek].ps && apStrings[q][0] != '\0') - OSD_Printf(cq ? OSDTEXT_DEFAULT "%s\n" : "%s\n", apStrings[q]); + auto qu = quoteMgr.GetQuote(q); + if (p == g_player[screenpeek].ps && qu[0] != '\0') + Printf((cq? PRINT_LOW : PRINT_MEDIUM) | PRINT_NOTIFY, "%s\n", qu); - p->ftq = q; - } + } - pub = NUMPAGES; - pus = NUMPAGES; + if (hud_messages == 1) + { + p->ftq = q; + p->fta = 100; + pub = NUMPAGES; + pus = NUMPAGES; + } } + +void GameInterface::DoPrintMessage(int prio, const char* t) +{ + auto p = g_player[myconnectindex].ps; // text quotes always belong to the local player. + int32_t cq = 0; + + if (hud_messages == 0 || !(p->gm & MODE_GAME)) + return; + + if (p->fta > 0) + if (p->ftq == QUOTE_RESERVED || p->ftq == QUOTE_RESERVED2) return; + + if (p == g_player[screenpeek].ps) + Printf(prio | PRINT_NOTIFY, cq ? OSDTEXT_DEFAULT "%s\n" : "%s\n", t); + + if (hud_messages == 1) + { + p->fta = 100; + p->ftq = -32768; + text_quote = t; + pub = NUMPAGES; + pus = NUMPAGES; + } + +} + + END_DUKE_NS diff --git a/source/duke3d/src/sector.cpp b/source/duke3d/src/sector.cpp index b29a9098d..7fd818867 100644 --- a/source/duke3d/src/sector.cpp +++ b/source/duke3d/src/sector.cpp @@ -2602,13 +2602,12 @@ void P_HandleSharedKeys(int playerNum) else ud.pause_on = 1+SHIFTS_IS_PRESSED; if (ud.pause_on) { - S_PauseMusic(true); + Mus_SetPaused(true); S_PauseSounds(true); } else { - if (MusicEnabled()) S_PauseMusic(false); - + Mus_SetPaused(false); S_PauseSounds(false); pub = NUMPAGES; diff --git a/source/duke3d/src/sector.h b/source/duke3d/src/sector.h index 031ac2a4a..4d1801ad3 100644 --- a/source/duke3d/src/sector.h +++ b/source/duke3d/src/sector.h @@ -106,12 +106,10 @@ extern void G_SaveMapState(); extern void G_RestoreMapState(); typedef struct { - int32_t partime, designertime; - char *name, *filename, *musicfn; mapstate_t *savedstate; } map_t; -//extern map_t g_mapInfo[(MAXVOLUMES+1)*MAXLEVELS]; // +1 volume for "intro", "briefing" music + void G_ActivateBySector(int sect,int spriteNum); int S_FindMusicSFX(int sectNum, int *sndptr); diff --git a/source/duke3d/src/sounds.cpp b/source/duke3d/src/sounds.cpp index ca4b4ecea..48949bdee 100644 --- a/source/duke3d/src/sounds.cpp +++ b/source/duke3d/src/sounds.cpp @@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "al_midi.h" #include "openaudio.h" #include "z_music.h" +#include "mapinfo.h" #include BEGIN_DUKE_NS @@ -83,16 +84,9 @@ void S_SoundStartup(void) g_sounds[i].num = 0; S_SetProperties(&voice, -1, 0, UINT16_MAX, 0); } - -#ifdef CACHING_DOESNT_SUCK - g_soundlocks[i] = 199; -#endif } - cacheAllSounds(); - snd_fxvolume.Callback(); - S_MusicVolume(mus_volume); snd_reversestereo.Callback(); FX_SetCallBack(S_Callback); @@ -101,9 +95,6 @@ void S_SoundStartup(void) void S_SoundShutdown(void) { - if (MusicVoice >= 0) - S_MusicShutdown(); - int status = FX_Shutdown(); if (status != FX_Ok) { @@ -112,45 +103,6 @@ void S_SoundShutdown(void) } } -void S_MusicStartup(void) -{ - initprintf("Initializing MIDI driver... "); - - int status; - if ((status = MUSIC_Init(MusicDevice)) == MUSIC_Ok) - { - if (MusicDevice == ASS_AutoDetect) - MusicDevice = MIDI_GetDevice(); - } - else if ((status = MUSIC_Init(ASS_AutoDetect)) == MUSIC_Ok) - { - MusicDevice = MIDI_GetDevice(); - } - else - { - initprintf("S_MusicStartup(): failed initializing: %s\n", MUSIC_ErrorString(status)); - return; - } - - MUSIC_SetVolume(mus_volume); - auto fr = kopenFileReader("d3dtimbr.tmb", 0); - - if (fr.isOpen()) - { - auto tmb = fr.Read(); - AL_RegisterTimbreBank(tmb.Data()); - } -} - -void S_MusicShutdown(void) -{ - S_StopMusic(); - - int status = MUSIC_Shutdown(); - if (status != MUSIC_Ok) - initprintf("S_MusicShutdown(): %s\n", MUSIC_ErrorString(status)); -} - void S_PauseSounds(bool paused) { if (SoundPaused == paused) @@ -166,30 +118,8 @@ void S_PauseSounds(bool paused) } } - -void S_MusicVolume(int32_t volume) -{ - if (MusicIsWaveform && MusicVoice >= 0) - FX_SetPan(MusicVoice, volume, volume, volume); - - MUSIC_SetVolume(volume); -} - -void S_RestartMusic(void) -{ - if (ud.recstat != 2 && g_player[myconnectindex].ps->gm&MODE_GAME) - { - S_PlayLevelMusicOrNothing(g_musicIndex); - } - else if (G_GetLogoFlags() & LOGO_PLAYMUSIC) - { - S_PlaySpecialMusicOrNothing(MUS_INTRO); - } -} - void S_MenuSound(void) { -#ifndef EDUKE32_STANDALONE static int SoundNum; int const menusnds[] = { LASERTRIP_EXPLODE, DUKE_GRUNT, DUKE_LAND_HURT, CHAINGUN_FIRE, SQUISHED, KICK_HIT, @@ -197,191 +127,39 @@ void S_MenuSound(void) PIPEBOMB_BOUNCE, PIPEBOMB_EXPLODE, NITEVISION_ONOFF, RPG_SHOOT, SELECT_WEAPON, }; int s = VM_OnEventWithReturn(EVENT_OPENMENUSOUND, g_player[screenpeek].ps->i, screenpeek, FURY ? -1 : menusnds[SoundNum++ % ARRAY_SIZE(menusnds)]); -#else - int s = VM_OnEventWithReturn(EVENT_OPENMENUSOUND, g_player[screenpeek].ps->i, screenpeek, -1); -#endif if (s != -1) S_PlaySound(s); } -#if 0 // In case you desperately want the old system back... ;) -static int S_PlayMusic(const char *, const char *fn, int loop) -{ - if (!MusicEnabled()) - return 0; - - if (fn == NULL) - return 1; - - auto fp = S_OpenAudio(fn, 0, 1); - if (!fp.isOpen()) - { - OSD_Printf(OSD_ERROR "S_PlayMusic(): error: can't open \"%s\" for playback!\n",fn); - return 2; - } - - int32_t MusicLen = fp.GetLength(); - - if (EDUKE32_PREDICT_FALSE(MusicLen < 4)) - { - OSD_Printf(OSD_ERROR "S_PlayMusic(): error: empty music file \"%s\"\n", fn); - return 3; - } - - char * MyMusicPtr = (char *)Xaligned_alloc(16, MusicLen); - int MyMusicSize = fp.Read(MyMusicPtr, MusicLen); - - if (EDUKE32_PREDICT_FALSE(MyMusicSize != MusicLen)) - { - OSD_Printf(OSD_ERROR "S_PlayMusic(): error: read %d bytes from \"%s\", expected %d\n", - MyMusicSize, fn, MusicLen); - ALIGNED_FREE_AND_NULL(MyMusicPtr); - return 4; - } - - if (!Bmemcmp(MyMusicPtr, "MThd", 4)) - { - int32_t retval = MUSIC_PlaySong(MyMusicPtr, MyMusicSize, MUSIC_LoopSong, fn); - - if (retval != MUSIC_Ok) - { - ALIGNED_FREE_AND_NULL(MyMusicPtr); - return 5; - } - - if (MusicIsWaveform && MusicVoice >= 0) - { - FX_StopSound(MusicVoice); - MusicVoice = -1; - } - - MusicIsWaveform = 0; - ALIGNED_FREE_AND_NULL(MusicPtr); - MusicPtr = MyMusicPtr; - g_musicSize = MyMusicSize; - } - else - { - int MyMusicVoice = FX_Play(MyMusicPtr, MusicLen, 0, 0, 0, mus_volume, mus_volume, mus_volume, - FX_MUSIC_PRIORITY, 1.f, MUSIC_ID); - - if (MyMusicVoice <= FX_Ok) - { - ALIGNED_FREE_AND_NULL(MyMusicPtr); - return 5; - } - - if (MusicIsWaveform && MusicVoice >= 0) - FX_StopSound(MusicVoice); - - MUSIC_StopSong(); - - MusicVoice = MyMusicVoice; - MusicIsWaveform = 1; - ALIGNED_FREE_AND_NULL(MusicPtr); - MusicPtr = MyMusicPtr; - g_musicSize = MyMusicSize; - } - - return 0; -} - -void S_StopMusic(void) -{ - MusicPaused = 0; - - if (MusicIsWaveform && MusicVoice >= 0) - { - FX_StopSound(MusicVoice); - MusicVoice = -1; - MusicIsWaveform = 0; - } - - MUSIC_StopSong(); - - ALIGNED_FREE_AND_NULL(MusicPtr); - g_musicSize = 0; -} - -void S_PauseMusic(bool paused) -{ - if (MusicPaused == paused || (MusicIsWaveform && MusicVoice < 0)) - return; - - MusicPaused = paused; - - if (MusicIsWaveform) - { - FX_PauseVoice(MusicVoice, paused); - return; - } - - if (paused) - MUSIC_Pause(); - else - MUSIC_Continue(); -} - -#else -static int S_PlayMusic(const char *mapname, const char* fn, bool looping = true) -{ - return Mus_Play(mapname, fn, looping); -} - -void S_StopMusic(void) -{ - Mus_Stop(); -} - -void S_PauseMusic(bool paused) -{ - Mus_SetPaused(paused); -} - - -#endif static void S_SetMusicIndex(unsigned int m) { - g_musicIndex = m; ud.music_episode = m / MAXLEVELS; ud.music_level = m % MAXLEVELS; } -bool S_TryPlayLevelMusic(unsigned int m) +void S_PlayLevelMusicOrNothing(unsigned int m) { ud.returnvar[0] = m / MAXLEVELS; ud.returnvar[1] = m % MAXLEVELS; int retval = VM_OnEvent(EVENT_PLAYLEVELMUSICSLOT, g_player[myconnectindex].ps->i, myconnectindex); - if (retval < 0) - return false; - - if (!S_PlayMusic(g_mapInfo[m].filename, g_mapInfo[m].musicfn)) - { - S_SetMusicIndex(m); - return false; - } - - return true; -} - -void S_PlayLevelMusicOrNothing(unsigned int m) -{ - if (S_TryPlayLevelMusic(m)) + if (retval >= 0) { - //S_StopMusic(); + // Thanks to scripting that stupid slot hijack cannot be refactored - but we'll store the real data elsewhere anyway! + auto &mr = m == USERMAPMUSICFAKESLOT ? userMapRecord : mapList[m]; + Mus_Play(mr.labelName, mr.music, true); S_SetMusicIndex(m); } } int S_TryPlaySpecialMusic(unsigned int m) { - char const * musicfn = g_mapInfo[m].musicfn; - if (musicfn != NULL) + auto &musicfn = mapList[m].music; + if (musicfn.IsNotEmpty()) { - if (!S_PlayMusic(nullptr, musicfn)) + if (!Mus_Play(nullptr, musicfn, true)) { S_SetMusicIndex(m); return 0; @@ -395,7 +173,6 @@ void S_PlaySpecialMusicOrNothing(unsigned int m) { if (S_TryPlaySpecialMusic(m)) { - //S_StopMusic(); S_SetMusicIndex(m); } } @@ -423,9 +200,6 @@ void S_Cleanup(void) // for which there was no open slot to keep track of the voice if (num >= (MAXSOUNDS*MAXSOUNDINSTANCES)) { -#ifdef CACHING_DOESNT_SUCK - --g_soundlocks[num-(MAXSOUNDS*MAXSOUNDINSTANCES)]; -#endif continue; } @@ -450,9 +224,6 @@ void S_Cleanup(void) S_SetProperties(&voice, -1, 0, UINT16_MAX, 0); -#ifdef CACHING_DOESNT_SUCK - --g_soundlocks[num]; -#endif } } @@ -473,9 +244,8 @@ int32_t S_LoadSound(int num) } int32_t l = fp.GetLength(); - g_soundlocks[num] = 255; snd.siz = l; - cacheAllocateBlock((intptr_t *)&snd.ptr, l, &g_soundlocks[num]); + cacheAllocateBlock((intptr_t *)&snd.ptr, l, nullptr); l = fp.Read(snd.ptr, l); return l; @@ -574,35 +344,6 @@ static int S_CalcDistAndAng(int spriteNum, int soundNum, int sectNum, int angle, sndang = S_GetAngle(angle, cam, pos); sndist = FindDistance3D(cam->x-pos->x, cam->y-pos->y, (cam->z-pos->z)); -#ifdef SPLITSCREEN_MOD_HACKS - if (g_fakeMultiMode==2) - { - // HACK for splitscreen mod: take the min of sound distances - // to 1st and 2nd player. - - if (PN(spriteNum) == APLAYER && P_Get(spriteNum) == 1) - { - sndist = sndang = 0; - goto sound_further_processing; - } - - { - const vec3_t *cam2 = &g_player[1].ps->pos; - int32_t sndist2 = FindDistance3D(cam2->x-pos->x, cam2->y-pos->y, (cam2->z-pos->z)); - - if (sndist2 < sndist) - { - cam = cam2; - sectNum = g_player[1].ps->cursectnum; - angle = g_player[1].ps->ang; - - sndist = sndist2; - sndang = S_GetAngle(angle, cam, pos); - } - } - } -#endif - if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) != SF_GLOBAL && S_IsAmbientSFX(spriteNum) && (sector[SECT(spriteNum)].lotag&0xff) < 9) // ST_9_SLIDING_ST_DOOR sndist = divscale14(sndist, SHT(spriteNum)+1); @@ -611,19 +352,13 @@ sound_further_processing: if (sndist < 0) sndist = 0; -#ifndef EDUKE32_STANDALONE if (!FURY && sectNum > -1 && sndist && PN(spriteNum) != MUSICANDSFX && !cansee(cam->x, cam->y, cam->z - (24 << 8), sectNum, SX(spriteNum), SY(spriteNum), SZ(spriteNum) - (24 << 8), SECT(spriteNum))) sndist += sndist>>5; -#else - UNREFERENCED_PARAMETER(sectNum); -#endif if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) == (SF_GLOBAL|SF_DTAG)) { -#ifndef EDUKE32_STANDALONE boost: -#endif int const sdist = g_sounds[soundNum].vo > 0 ? g_sounds[soundNum].vo : 6144; explosion = true; @@ -631,8 +366,6 @@ boost: if (sndist > sdist) sndist = sdist; } - -#ifndef EDUKE32_STANDALONE else if (!FURY) { switch (DYNAMICSOUNDMAP(soundNum)) @@ -643,7 +376,6 @@ boost: goto boost; } } -#endif if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) == SF_GLOBAL || sndist < ((255-LOUDESTVOLUME) << 6)) sndist = ((255-LOUDESTVOLUME) << 6); @@ -703,13 +435,6 @@ int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) while (j < MAXSOUNDINSTANCES && snd.voices[j].id != voice) j++; -#ifdef DEBUGGINGAIDS - if (EDUKE32_PREDICT_FALSE(j >= MAXSOUNDINSTANCES)) - { - OSD_Printf(OSD_ERROR "%s %d: WTF?\n", __FILE__, __LINE__); - return -1; - } -#endif snd.voices[j].owner = spriteNum; @@ -721,14 +446,6 @@ int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) int pitch = S_GetPitch(sndNum); auto const pOther = g_player[screenpeek].ps; -#ifdef SPLITSCREEN_MOD_HACKS - if (g_fakeMultiMode==2) - { - // splitscreen HACK - if (g_player[1].ps->i == spriteNum) - pOther = g_player[1].ps; -} -#endif if (pOther->sound_pitch) pitch += pOther->sound_pitch; @@ -751,18 +468,10 @@ int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) if (snd.num > 0 && PN(spriteNum) != MUSICANDSFX) S_StopEnvSound(sndNum, spriteNum); -#ifdef CACHING_DOESNT_SUCK - if (++g_soundlocks[sndNum] < 200) - g_soundlocks[sndNum] = 200; -#endif - int const sndSlot = S_GetSlot(sndNum); if (sndSlot >= MAXSOUNDINSTANCES) { -#ifdef CACHING_DOESNT_SUCK - g_soundlocks[sndNum]--; -#endif return -1; } @@ -770,9 +479,6 @@ int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) if (repeatp && (snd.m & SF_ONEINST_INTERNAL) && snd.num > 0) { -#ifdef CACHING_DOESNT_SUCK - g_soundlocks[sndNum]--; -#endif return -1; } @@ -781,9 +487,6 @@ int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) if (voice <= FX_Ok) { -#ifdef CACHING_DOESNT_SUCK - g_soundlocks[sndNum]--; -#endif return -1; } @@ -816,18 +519,10 @@ int S_PlaySound(int num) int const pitch = S_GetPitch(num); -#ifdef CACHING_DOESNT_SUCK - if (++g_soundlocks[num] < 200) - g_soundlocks[num] = 200; -#endif - sndnum = S_GetSlot(num); if (sndnum >= MAXSOUNDINSTANCES) { -#ifdef CACHING_DOESNT_SUCK - g_soundlocks[num]--; -#endif return -1; } @@ -838,9 +533,6 @@ int S_PlaySound(int num) if (voice <= FX_Ok) { -#ifdef CACHING_DOESNT_SUCK - g_soundlocks[num]--; -#endif return -1; } @@ -876,11 +568,6 @@ void S_StopEnvSound(int sndNum, int sprNum) if ((sprNum == -1 && voice.id > FX_Ok) || (sprNum != -1 && voice.owner == sprNum)) { -#ifdef DEBUGGINGAIDS - if (EDUKE32_PREDICT_FALSE(sprNum >= 0 && voice.id <= FX_Ok)) - initprintf(OSD_ERROR "S_StopEnvSound(): bad voice %d for sound ID %d index %d!\n", voice.id, sndNum, j); - else -#endif if (voice.id > FX_Ok) { if (FX_SoundActive(voice.id)) @@ -996,18 +683,6 @@ void S_Callback(intptr_t num) mutex_unlock(&m_callback); } -void S_ClearSoundLocks(void) -{ -#ifdef CACHING_DOESNT_SUCK - int32_t i; - int32_t const msp = g_highestSoundIdx; - - for (native_t i = 0; i <= msp; ++i) - if (g_soundlocks[i] >= 200) - g_soundlocks[i] = 199; -#endif -} - int A_CheckSoundPlaying(int spriteNum, int soundNum) { if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return 0; diff --git a/source/duke3d/src/sounds.h b/source/duke3d/src/sounds.h index fab55af82..428815125 100644 --- a/source/duke3d/src/sounds.h +++ b/source/duke3d/src/sounds.h @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define sounds_public_h_ #include "sounds_common.h" +#include "z_music.h" BEGIN_DUKE_NS @@ -57,7 +58,6 @@ typedef struct char pr, m; // 2b } sound_t; -extern uint8_t g_soundlocks[MAXSOUNDS]; extern sound_t g_sounds[MAXSOUNDS]; extern int32_t g_numEnvSoundsPlaying,g_highestSoundIdx; @@ -67,17 +67,12 @@ void S_Callback(intptr_t num); int A_CheckAnySoundPlaying(int spriteNum); int S_CheckSoundPlaying(int soundNum); void S_Cleanup(void); -void S_ClearSoundLocks(void); +inline void S_ClearSoundLocks(void) {} int32_t S_LoadSound(uint32_t num); void cacheAllSounds(void); void S_MenuSound(void); -void S_MusicShutdown(void); -void S_MusicStartup(void); -void S_MusicVolume(int32_t volume); -void S_RestartMusic(void); void S_PauseMusic(bool paused); void S_PauseSounds(bool paused); -bool S_TryPlayLevelMusic(unsigned int m); void S_PlayLevelMusicOrNothing(unsigned int); int S_TryPlaySpecialMusic(unsigned int); void S_PlaySpecialMusicOrNothing(unsigned int); @@ -88,7 +83,6 @@ void S_SoundShutdown(void); void S_SoundStartup(void); void S_StopEnvSound(int sndNum,int sprNum); void S_StopAllSounds(void); -void S_StopMusic(void); void S_Update(void); void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset); diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 37cc41136..a124002d9 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -69,7 +69,6 @@ void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch) FHardwareTexture* GLInstance::CreateIndexedTexture(FTexture* tex) { auto siz = tex->GetSize(); - bool npoty = false; const uint8_t* p = tex->Get8BitPixels(); TArray store(siz.x * siz.y, true); @@ -96,11 +95,8 @@ FHardwareTexture* GLInstance::CreateIndexedTexture(FTexture* tex) FHardwareTexture* GLInstance::CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit) { - auto siz = tex->GetSize(); - bool npoty = false; - auto palette = palid < 0? nullptr : palmanager.GetPaletteData(palid); - if (palette == nullptr) return nullptr; + if (palid >= 0 && palette == nullptr) return nullptr; auto texbuffer = tex->CreateTexBuffer(palette, CTF_ProcessData); // Check if the texture is fully transparent. When creating a brightmap such textures can be discarded. if (checkfulltransparency) @@ -266,7 +262,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int auto brep = tex->FindReplacement(BRIGHTPAL); if (brep) { - auto htex = LoadTexture(brep->faces[0], TT_HICREPLACE, 0); + LoadTexture(brep->faces[0], TT_HICREPLACE, 0); UseBrightmaps(true); BindTexture(5, mtex, sampler); } diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 4b222a273..ecad690b1 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -49,7 +49,7 @@ extern int ydim; FileReader GetResource(const char* fn) { - auto fr = kopenFileReader(fn, 0); + auto fr = fileSystem.OpenFileReader(fn, 0); if (!fr.isOpen()) { I_Error("Fatal: '%s' not found", fn); @@ -104,8 +104,8 @@ void GLInstance::Init(int ydim) ImGui_ImplOpenGL3_Init(); if (!ttf.Size()) { - //ttf = kloadfile("demolition/Capsmall_clean.ttf", 0); - ttf = kloadfile("demolition/Roboto-Regular.ttf", 0); + //ttf = fileSystem.LoadFile("demolition/Capsmall_clean.ttf", 0); + ttf = fileSystem.LoadFile("demolition/Roboto-Regular.ttf", 0); } if (ttf.Size()) io.Fonts->AddFontFromMemoryTTF(ttf.Data(), ttf.Size(), std::clamp(ydim / 40, 10, 30)); } diff --git a/source/glbackend/hw_draw2d.cpp b/source/glbackend/hw_draw2d.cpp index 68e62bd9b..c9ec925d0 100644 --- a/source/glbackend/hw_draw2d.cpp +++ b/source/glbackend/hw_draw2d.cpp @@ -82,6 +82,7 @@ public: // Draws the 2D stuff. This is the version for OpenGL 3 and later. // //=========================================================================== +void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid); void GLInstance::Draw2D(F2DDrawer *drawer) { @@ -123,6 +124,28 @@ void GLInstance::Draw2D(F2DDrawer *drawer) for(auto &cmd : commands) { + if (cmd.mType == F2DDrawer::DrawTypeRotateSprite) + { + // This just gets forwarded to the original drawer. Long term this should not survive and all calls be refactored. + UseColorOnly(false); + SetFadeDisable(false); + SetVertexBuffer(nullptr, 0, 0); + SetIndexBuffer(nullptr); + polymost_dorotatesprite(cmd.mVertIndex, cmd.mVertCount, cmd.mIndexIndex, cmd.mIndexCount, cmd.mSpecialColormap[0].d, cmd.mRemapIndex, cmd.mFlags, cmd.mSpecialColormap[1].d, + cmd.mDesaturate, cmd.mColor1.d, cmd.mScissor[0], cmd.mScissor[1], cmd.mScissor[2], cmd.mScissor[3], 0); + // Reset everything to the default. + SetFadeDisable(true); + EnableDepthTest(false); + EnableMultisampling(false); + EnableBlend(true); + EnableAlphaTest(true); + SetBlendFunc(STYLEALPHA_Src, STYLEALPHA_InvSrc); + SetVertexBuffer(vb.GetBufferObjects().first, 0, 0); + SetIndexBuffer(vb.GetBufferObjects().second); + + continue; + } + int gltrans = -1; //state.SetRenderStyle(cmd.mRenderStyle); diff --git a/source/libsmackerdec/src/FileStream.cpp b/source/libsmackerdec/src/FileStream.cpp index a14428392..5fd112fc1 100644 --- a/source/libsmackerdec/src/FileStream.cpp +++ b/source/libsmackerdec/src/FileStream.cpp @@ -18,14 +18,14 @@ */ #include "FileStream.h" -#include "cache1d.h" +#include "filesystem/filesystem.h" #include namespace SmackerCommon { bool FileStream::Open(const std::string &fileName) { - file = kopenFileReader(fileName.c_str(), 0); + file = fileSystem.OpenFileReader(fileName.c_str(), 0); if (!file.isOpen()) { // log error diff --git a/source/mact/include/input.h b/source/mact/include/input.h index 1028331e0..46917dca2 100644 --- a/source/mact/include/input.h +++ b/source/mact/include/input.h @@ -47,25 +47,6 @@ extern void I_GeneralTriggerClear(void); extern int32_t I_EscapeTrigger(void); extern void I_EscapeTriggerClear(void); -extern int32_t I_MenuUp(void); -extern void I_MenuUpClear(void); -extern int32_t I_MenuDown(void); -extern void I_MenuDownClear(void); -extern int32_t I_MenuLeft(void); -extern void I_MenuLeftClear(void); -extern int32_t I_MenuRight(void); -extern void I_MenuRightClear(void); - -extern int32_t I_PanelUp(void); -extern void I_PanelUpClear(void); -extern int32_t I_PanelDown(void); -extern void I_PanelDownClear(void); - -extern int32_t I_SliderLeft(void); -extern void I_SliderLeftClear(void); -extern int32_t I_SliderRight(void); -extern void I_SliderRightClear(void); - enum EnterTextFlags_t { INPUT_NUMERIC = 0x00000001, diff --git a/source/mact/src/input.cpp b/source/mact/src/input.cpp index cfe298978..3687637a7 100644 --- a/source/mact/src/input.cpp +++ b/source/mact/src/input.cpp @@ -31,6 +31,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. char typebuf[TYPEBUFSIZE]; +bool mouseInactiveConditional(bool condition) +{ + return condition; +} int32_t I_CheckAllInput(void) { @@ -54,7 +58,7 @@ int32_t I_TextSubmit(void) return inputState.GetKeyStatus(sc_Enter) || inputState.GetKeyStatus(sc_kpad_Enter) - || gi->mouseInactiveConditional(inputState.MouseGetButtons()&LEFT_MOUSE) + || mouseInactiveConditional(inputState.MouseGetButtons()&LEFT_MOUSE) || (JOYSTICK_GetGameControllerButtons()&(1<mouseInactiveConditional(buttonMap.ButtonDown(gamefunc_Fire)) + || mouseInactiveConditional(buttonMap.ButtonDown(gamefunc_Fire)) || buttonMap.ButtonDown(gamefunc_Crouch) || (JOYSTICK_GetGameControllerButtons()&(1<mouseInactiveConditional((inputState.MouseGetButtons()&LEFT_MOUSE) && (inputState.MouseGetButtons()&WHEELUP_MOUSE)) -#endif - ; -} - -void I_SliderLeftClear(void) -{ - I_MenuLeftClear(); - inputState.MouseClearButton(WHEELUP_MOUSE); -} - - -int32_t I_SliderRight(void) -{ - return - I_MenuRight() -#if !defined EDUKE32_TOUCH_DEVICES - || gi->mouseInactiveConditional((inputState.MouseGetButtons()&LEFT_MOUSE) && (inputState.MouseGetButtons()&WHEELDOWN_MOUSE)) -#endif - ; -} - -void I_SliderRightClear(void) -{ - I_MenuRightClear(); - inputState.MouseClearButton(WHEELDOWN_MOUSE); -} - - int32_t I_EnterText(char *t, int32_t maxlength, int32_t flags) { char ch; diff --git a/source/platform/gtk/startgtk.game.cpp b/source/platform/gtk/startgtk.game.cpp index f21b92a4f..8f363973b 100644 --- a/source/platform/gtk/startgtk.game.cpp +++ b/source/platform/gtk/startgtk.game.cpp @@ -108,7 +108,9 @@ static struct grpfile_t const * grp; char *gamedir; ud_setup_t shared; +#ifdef POLYMER int polymer; +#endif } settings; static int32_t retval = -1, mode = TAB_MESSAGES; @@ -130,6 +132,7 @@ static void on_vmode3dcombo_changed(GtkComboBox *combobox, gpointer user_data) gtk_tree_model_get(data, &iter, 1, &val, -1); settings.shared.xdim = validmode[val].xdim; settings.shared.ydim = validmode[val].ydim; + settings.shared.bpp = validmode[val].bpp; } static void on_fullscreencheck_toggled(GtkToggleButton *togglebutton, gpointer user_data) @@ -272,7 +275,7 @@ static unsigned char GetModsDirNames(GtkListStore *list) char *homedir; char pdir[BMAX_PATH]; unsigned char iternumb = 0; - CACHE1D_FIND_REC *dirs = NULL; + BUILDVFS_FIND_REC *dirs = NULL; GtkTreeIter iter; pathsearchmode = 1; @@ -280,7 +283,7 @@ static unsigned char GetModsDirNames(GtkListStore *list) if ((homedir = Bgethomedir())) { Bsnprintf(pdir, sizeof(pdir), "%s/" ".eduke32", homedir); - dirs = klistpath(pdir, "*", CACHE1D_FIND_DIR); + dirs = klistpath(pdir, "*", BUILDVFS_FIND_DIR); for (; dirs != NULL; dirs=dirs->next) { if ((Bstrcmp(dirs->name, "autoload") == 0) || @@ -866,9 +869,7 @@ int32_t startwin_run(void) settings.gamedir = g_modDir; settings.grp = g_selectedGrp; #ifdef POLYMER - settings.polymer = (glrendmode == REND_POLYMER); -#else - settings.polymer = 0; + settings.polymer = (glrendmode == REND_POLYMER) & (settings.shared.bpp != 8); #endif PopulateForm(ALL); @@ -878,7 +879,9 @@ int32_t startwin_run(void) if (retval) // launch the game with these parameters { ud.setup = settings.shared; +#ifdef POLYMER glrendmode = (settings.polymer) ? REND_POLYMER : REND_POLYMOST; +#endif g_selectedGrp = settings.grp; Bstrcpy(g_modDir, (g_noSetup == 0 && settings.gamedir != NULL) ? settings.gamedir : "/"); diff --git a/source/platform/macos/osxbits.h b/source/platform/macos/osxbits.h index 8a35e14df..639e48869 100644 --- a/source/platform/macos/osxbits.h +++ b/source/platform/macos/osxbits.h @@ -2,6 +2,9 @@ #define osxbits_h_ #include +void osx_preopen(void); +void osx_postopen(void); + int osx_msgbox(const char *name, const char *msg); int osx_ynbox(const char *name, const char *msg); diff --git a/source/platform/macos/osxbits.mm b/source/platform/macos/osxbits.mm index 613d6b554..16f04ec01 100644 --- a/source/platform/macos/osxbits.mm +++ b/source/platform/macos/osxbits.mm @@ -23,6 +23,20 @@ # define MAC_OS_VERSION_10_3 1030 #endif +id nsapp; + +void osx_preopen(void) +{ + // fix for "ld: absolute address to symbol _NSApp in a different linkage unit not supported" + // (OS X 10.6) when building for PPC + nsapp = [NSApplication sharedApplication]; +} + +void osx_postopen(void) +{ + [nsapp finishLaunching]; +} + int osx_msgbox(const char *name, const char *msg) { NSString *mmsg = [[NSString alloc] initWithUTF8String:msg]; diff --git a/source/platform/macos/startosx.game.mm b/source/platform/macos/startosx.game.mm index 731a4634f..b88b589e8 100644 --- a/source/platform/macos/startosx.game.mm +++ b/source/platform/macos/startosx.game.mm @@ -11,6 +11,7 @@ #include "compat.h" #include "baselayer.h" #include "grpscan.h" +#include "osxbits.h" #import "GrpFile.game.h" #import "GameListSource.game.h" @@ -105,8 +106,6 @@ static NSPopUpButton * makeComboBox(void) return comboBox; } -static id nsapp; - /* setAppleMenu disappeared from the headers in 10.4 */ @interface NSApplication(NSAppleMenu) - (void)setAppleMenu:(NSMenu *)menu; @@ -599,10 +598,6 @@ static StartupWindow *startwin = nil; int startwin_open(void) { - // fix for "ld: absolute address to symbol _NSApp in a different linkage unit not supported" - // (OS X 10.6) when building for PPC - nsapp = [NSApplication sharedApplication]; - if (startwin != nil) return 1; startwin = [[StartupWindow alloc] init]; @@ -610,8 +605,6 @@ int startwin_open(void) [startwin setupMessagesMode]; - [nsapp finishLaunching]; - [startwin center]; [startwin makeKeyAndOrderFront:nil]; diff --git a/source/platform/win32/startwin.game.cpp b/source/platform/win32/startwin.game.cpp index 60d387675..592c93ecc 100644 --- a/source/platform/win32/startwin.game.cpp +++ b/source/platform/win32/startwin.game.cpp @@ -432,7 +432,6 @@ static INT_PTR CALLBACK startup_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, case WM_CLOSE: if (mode == TAB_CONFIG) done = 0; - else quitevent++; return TRUE; case WM_DESTROY: @@ -456,7 +455,6 @@ static INT_PTR CALLBACK startup_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, { case WIN_STARTWIN_CANCEL: if (mode == TAB_CONFIG) done = 0; - else quitevent++; return TRUE; case WIN_STARTWIN_START: done = 1; diff --git a/source/rr/CMakeLists.txt b/source/rr/CMakeLists.txt index 43ee43de1..7d7cd7e00 100644 --- a/source/rr/CMakeLists.txt +++ b/source/rr/CMakeLists.txt @@ -31,9 +31,9 @@ include_directories( set( NOT_COMPILED_SOURCE_FILES ) - + set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE ) - + set( PCH_SOURCES src/actors.cpp src/anim.cpp @@ -41,6 +41,7 @@ set( PCH_SOURCES src/cmdline.cpp src/common.cpp src/config.cpp + src/d_menu.cpp src/demo.cpp src/game.cpp src/gamedef.cpp @@ -69,7 +70,7 @@ if( MSVC ) else() # Temporary solution for compilers other than MSVC set_source_files_properties( ${PCH_SOURCES} PROPERTIES COMPILE_FLAGS "-include g_pch.h" ) -endif() +endif() file( GLOB HEADER_FILES src/*.h @@ -79,5 +80,3 @@ add_library( rr STATIC ${PCH_SOURCES} ${NOT_COMPILED_SOURCE_FILES} ) - - diff --git a/source/rr/src/actors.cpp b/source/rr/src/actors.cpp index 12ae0d40c..00bcadf60 100644 --- a/source/rr/src/actors.cpp +++ b/source/rr/src/actors.cpp @@ -9142,13 +9142,13 @@ next_sprite: static void G_DoEffectorLights(void) // STATNUM 14 { - int32_t i; +#ifdef POLYMER + int32_t i; for (SPRITES_OF(STAT_LIGHT, i)) { switch (sprite[i].lotag) { -#ifdef POLYMER case SE_49_POINT_LIGHT: { if (!A_CheckSpriteFlags(i, SFLAG_NOLIGHT) && videoGetRenderMode() == REND_POLYMER && @@ -9310,9 +9310,9 @@ static void G_DoEffectorLights(void) // STATNUM 14 break; } -#endif // POLYMER } } +#endif // POLYMER } #ifdef POLYMER diff --git a/source/rr/src/anim.cpp b/source/rr/src/anim.cpp index fd86e2d32..9496492cb 100644 --- a/source/rr/src/anim.cpp +++ b/source/rr/src/anim.cpp @@ -289,7 +289,7 @@ int32_t Anim_Play(const char *fn) FileReader handle; if (!Bstrcmp(dot, ".ivf")) { - handle = kopenFileReader(fn, 0); + handle = fileSystem.OpenFileReader(fn, 0); if (!handle.isOpen()) break; } @@ -308,7 +308,7 @@ int32_t Anim_Play(const char *fn) vpxfndot[3] = 'f'; vpxfndot[4] = '\0'; - handle = kopenFileReader(vpxfn, 0); + handle = fileSystem.OpenFileReader(vpxfn, 0); if (!handle.isOpen()) break; @@ -451,7 +451,7 @@ int32_t Anim_Play(const char *fn) #ifdef USE_OPENGL int32_t ogltexfiltermode = hw_texfilter; #endif - auto fr = kopenFileReader(fn, 0); + auto fr = fileSystem.OpenFileReader(fn, 0); if (!fr.isOpen()) return 0; @@ -494,7 +494,6 @@ int32_t Anim_Play(const char *fn) // setpalette(0L,256L,tempbuf); P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 8 + 2); - timerUpdate(); ototalclock = totalclock; i = 1; diff --git a/source/rr/src/cheats.cpp b/source/rr/src/cheats.cpp index d2e315636..67be9c56f 100644 --- a/source/rr/src/cheats.cpp +++ b/source/rr/src/cheats.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "duke3d.h" #include "osdcmds.h" #include "cheats.h" +#include "mapinfo.h" BEGIN_RR_NS @@ -211,9 +212,6 @@ void G_SetupCheats(void) Bstrcpy(CheatStrings[23], ""); Bstrcpy(CheatStrings[24], "adebug"); Bstrcpy(CheatStrings[26], "acgs"); - - Bstrcpy(g_gametypeNames[0], "GruntMatch (Spawn)"); - Bstrcpy(g_gametypeNames[2], "GruntMatch (No Spawn)"); } } @@ -490,7 +488,7 @@ void G_DoCheats(void) //} //else //{ - // Bstrcpy(apStrings[QUOTE_RESERVED4], "Come Get Some!"); + // Bstrcpy(pStrings[QUOTE_RESERVED4], "Come Get Some!"); // // S_PlaySound(DUKE_GETWEAPON2); // P_DoQuote(QUOTE_RESERVED4, pPlayer); @@ -557,7 +555,7 @@ void G_DoCheats(void) int32_t const volnume = ud.m_volume_number, levnume = m_level_number; if ((!VOLUMEONE || volnume == 0) && (unsigned)volnume < (unsigned)g_volumeCnt && - (unsigned)levnume < MAXLEVELS && g_mapInfo[volnume*MAXLEVELS + levnume].filename != NULL) + (unsigned)levnume < MAXLEVELS && mapList[volnume*MAXLEVELS + levnume].fileName.IsNotEmpty()) { ud.volume_number = volnume; ud.level_number = levnume; @@ -661,7 +659,7 @@ void G_DoCheats(void) case CHEAT_TODD: if (NAM) { - Bstrcpy(apStrings[QUOTE_RESERVED4], g_NAMMattCheatQuote); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, g_NAMMattCheatQuote); P_DoQuote(QUOTE_RESERVED4, pPlayer); } else @@ -693,12 +691,12 @@ void G_DoCheats(void) case CHEAT_MONSTERS: { - const char *s [] = { "On", "Off", "On (2)" }; + const char *s [] = { "OPTVAL_ON", "OPTVAL_OFF", "$TXT_ON2" }; if (++g_noEnemies == 3) g_noEnemies = 0; - Bsprintf(apStrings[QUOTE_RESERVED4], "Monsters: %s", s[g_noEnemies]); + quoteMgr.FormatQuote(QUOTE_RESERVED4, "%s: %s", GStrings("NETMNU_MONSTERS"), s[g_noEnemies]); P_DoQuote(QUOTE_RESERVED4, pPlayer); end_cheat(pPlayer); diff --git a/source/rr/src/common.cpp b/source/rr/src/common.cpp index 67af9e974..4ad9d1f6c 100644 --- a/source/rr/src/common.cpp +++ b/source/rr/src/common.cpp @@ -105,7 +105,7 @@ void G_LoadLookups(void) { int32_t j; - auto fr = kopenFileReader("lookup.dat", 0); + auto fr = fileSystem.OpenFileReader("lookup.dat", 0); if (!fr.isOpen()) return; diff --git a/source/rr/src/config.cpp b/source/rr/src/config.cpp index 8a11aeb15..e46e80aa9 100644 --- a/source/rr/src/config.cpp +++ b/source/rr/src/config.cpp @@ -86,7 +86,6 @@ void CONFIG_SetDefaults(void) ud.show_level_text = 1; ud.screenfade = 1; ud.menubackground = 1; - ud.default_skill = 1; ud.slidebar_paldisabled = 1; ud.shadow_pal = 4; ud.menu_scrollbartilenum = -1; diff --git a/source/rr/src/d_menu.cpp b/source/rr/src/d_menu.cpp new file mode 100644 index 000000000..d275f62fb --- /dev/null +++ b/source/rr/src/d_menu.cpp @@ -0,0 +1,518 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2016 EDuke32 developers and contributors +Copyright (C) 2019 Christoph Oelckers + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- + +#include "ns.h" // Must come before everything else! + +#include "cheats.h" +#include "compat.h" +#include "demo.h" +#include "duke3d.h" +#include "input.h" +#include "menus.h" +#include "osdcmds.h" +#include "savegame.h" +#include "game.h" +#include "superfasthash.h" +#include "gamecvars.h" +#include "gamecontrol.h" +#include "c_bind.h" +#include "menu/menu.h" +#include "gstrings.h" +#include "version.h" +#include "namesdyn.h" +#include "../../glbackend/glbackend.h" + + +BEGIN_RR_NS + +#define MENU_MARGIN_REGULAR 40 +#define MENU_MARGIN_WIDE 32 +#define MENU_MARGIN_CENTER 160 +#define MENU_HEIGHT_CENTER 100 + + +enum MenuTextFlags_t +{ + MT_Selected = 1 << 0, + MT_Disabled = 1 << 1, + MT_XCenter = 1 << 2, + MT_XRight = 1 << 3, + MT_YCenter = 1 << 4, + MT_Literal = 1 << 5, + MT_RightSide = 1 << 6, +}; + + +// common font types +// tilenums are set after namesdyn runs. +// These are also modifiable by scripts. +// emptychar x,y between x,y zoom cursorLeft cursorCenter cursorScale textflags +// tilenum shade_deselected shade_disabled pal pal_selected pal_deselected pal_disabled +MenuFont_t MF_Redfont = { { 5<<16, 15<<16 }, { 0, 0 }, 65536, 20<<16, 110<<16, 65536, 65536, 65536, TEXT_BIGALPHANUM | TEXT_UPPERCASE, + -1, 10, 0, 0, 0, 0, 1, + 0, 0, 1 }; +MenuFont_t MF_Bluefont = { { 5<<16, 7<<16 }, { 0, 0 }, 65536, 10<<16, 110<<16, 32768, 65536, 65536, 0, + -1, 10, 0, 0, 10, 10, 16, + 0, 0, 16 }; +MenuFont_t MF_Minifont = { { 4<<16, 5<<16 }, { 1<<16, 1<<16 }, 65536, 10<<16, 110<<16, 32768, 65536, 65536, 0, + -1, 10, 0, 0, 2, 2, 0, + 0, 0, 16 }; + + +/* +This function prepares data after ART and CON have been processed. +It also initializes some data in loops rather than statically at compile time. +*/ + +void Menu_Init(void) +{ + + // prepare menu fonts + // check if tilenum is -1 in case it was set in EVENT_SETDEFAULTS + if ((unsigned)MF_Redfont.tilenum >= MAXTILES) MF_Redfont.tilenum = BIGALPHANUM; + if ((unsigned)MF_Bluefont.tilenum >= MAXTILES) MF_Bluefont.tilenum = STARTALPHANUM; + if ((unsigned)MF_Minifont.tilenum >= MAXTILES) MF_Minifont.tilenum = MINIFONT; + MF_Redfont.emptychar.y = tilesiz[MF_Redfont.tilenum].y << 16; + MF_Bluefont.emptychar.y = tilesiz[MF_Bluefont.tilenum].y << 16; + MF_Minifont.emptychar.y = tilesiz[MF_Minifont.tilenum].y << 16; + if (!minitext_lowercase) + MF_Minifont.textflags |= TEXT_UPPERCASE; + +#if 0 + + // prepare sound setup +#ifndef EDUKE32_STANDALONE + if (WW2GI) + ME_SOUND_DUKETALK.name = "GI talk:"; + else if (NAM) + ME_SOUND_DUKETALK.name = "Grunt talk:"; + ME_SOUND_DUKETALK.name = "Leonard Talk:"; + +#endif + + // prepare pre-Atomic + if (!VOLUMEALL || !PLUTOPAK) + { + // prepare credits + M_CREDITS.title = M_CREDITS2.title = M_CREDITS3.title = s_Credits; + } +#endif + + if (RR) + { + MF_Redfont.zoom = 32768; + MF_Redfont.emptychar.x <<= 1; + MF_Redfont.cursorScale = 13107; + MF_Redfont.cursorScale2 = 6553; + //MF_Redfont.emptychar.y <<= 1; + MF_Bluefont.zoom = 32768; + MF_Bluefont.emptychar.x <<= 1; + MF_Bluefont.cursorScale = 6553; + MF_Bluefont.cursorScale2 = 6553; + //MF_Bluefont.emptychar.y <<= 1; + MF_Minifont.zoom = 32768; + MF_Minifont.emptychar.x <<= 1; + MF_Minifont.cursorScale = 6553; + MF_Minifont.cursorScale2 = 6553; + //MF_Minifont.emptychar.y <<= 1; + } + +} + + +static void Menu_DrawBackground(const DVector2 &origin) +{ + rotatesprite_fs(int(origin.X * 65536) + (MENU_MARGIN_CENTER << 16), int(origin.Y * 65536) + (100 << 16), 65536L, 0, MENUSCREEN, 16, 0, 10 + 64); +} + +static void Menu_DrawTopBar(const DVector2 &origin) +{ + rotatesprite_fs(int(origin.X*65536) + (MENU_MARGIN_CENTER<<16), int(origin.Y*65536) + (19<<16), MF_Redfont.cursorScale3, 0,MENUBAR,16,0,10); +} + +static void Menu_DrawTopBarCaption(const char* caption, const DVector2& origin) +{ + static char t[64]; + size_t const srclen = strlen(caption); + size_t const dstlen = min(srclen, ARRAY_SIZE(t) - 1); + memcpy(t, caption, dstlen); + t[dstlen] = '\0'; + char* p = &t[dstlen - 1]; + if (*p == ':') + *p = '\0'; + captionmenutext(int(origin.X * 65536) + (MENU_MARGIN_CENTER << 16), int(origin.Y * 65536) + (24 << 16) + (15 << 15), t); +} + +static void Menu_GetFmt(const MenuFont_t* font, uint8_t const status, int32_t* s) +{ + if (status & MT_Selected) + *s = sintable[((int32_t)totalclock << 5) & 2047] >> 12; + else + *s = font->shade_deselected; + // sum shade values + if (status & MT_Disabled) + *s += font->shade_disabled; +} + +static vec2_t Menu_Text(int32_t x, int32_t y, const MenuFont_t* font, const char* t, uint8_t status, int32_t ydim_upper, int32_t ydim_lower) +{ + int32_t s, p, ybetween = font->between.y; + int32_t f = font->textflags | TEXT_RRMENUTEXTHACK; + if (status & MT_XCenter) + f |= TEXT_XCENTER; + if (status & MT_XRight) + f |= TEXT_XRIGHT; + if (status & MT_YCenter) + { + f |= TEXT_YCENTER | TEXT_YOFFSETZERO; + ybetween = font->emptychar.y; // <^ the battle against 'Q' + } + if (status & MT_Literal) + f |= TEXT_LITERALESCAPE; + + int32_t z = font->zoom; + + if (status & MT_Disabled) + p = (status & MT_RightSide) ? font->pal_disabled_right : font->pal_disabled; + else if (status & MT_Selected) + p = (status & MT_RightSide) ? font->pal_selected_right : font->pal_selected; + else + p = (status & MT_RightSide) ? font->pal_deselected_right : font->pal_deselected; + + Menu_GetFmt(font, status, &s); + + return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim - 1, ydim_lower); +} + +static int32_t Menu_CursorShade(void) +{ + return 4 - (sintable[((int32_t)totalclock << 4) & 2047] >> 11); +} + +static void Menu_DrawCursorCommon(int32_t x, int32_t y, int32_t z, int32_t picnum, int32_t ydim_upper = 0, int32_t ydim_lower = ydim - 1) +{ + rotatesprite_(x, y, z, 0, picnum, Menu_CursorShade(), 0, 2 | 8, 0, 0, 0, ydim_upper, xdim - 1, ydim_lower); +} + +static void Menu_DrawCursorLeft(int32_t x, int32_t y, int32_t z) +{ + const int frames = RR ? 16 : 7; + Menu_DrawCursorCommon(x, y, z, SPINNINGNUKEICON+(((int32_t) totalclock>>3)%frames)); +} + +static void Menu_DrawCursorRight(int32_t x, int32_t y, int32_t z) +{ + const int frames = RR ? 16 : 7; + Menu_DrawCursorCommon(x, y, z, SPINNINGNUKEICON+frames-1-((frames-1+((int32_t) totalclock>>3))%frames)); +} + +static int Menu_GetFontHeight(int fontnum) +{ + auto& font = fontnum == NIT_BigFont ? MF_Redfont : fontnum == NIT_SmallFont ? MF_Bluefont : MF_Minifont; + return font.get_yline(); +} + +//---------------------------------------------------------------------------- +// +// Implements the native looking menu used for the main menu +// and the episode/skill selection screens, i.e. the parts +// that need to look authentic +// +//---------------------------------------------------------------------------- + +class RedneckListMenu : public DListMenu +{ + using Super = DListMenu; +protected: + + void Ticker() override + { + // Lay out the menu. + int32_t y_upper = mDesc->mYpos; + int32_t y_lower = y_upper + mDesc->mYbotton; + int32_t y = 0; + int32_t calculatedentryspacing = 0; + int32_t const height = Menu_GetFontHeight(mDesc->mNativeFontNum) >> 16; + + int32_t totalheight = 0, numvalidentries = mDesc->mItems.Size(); + + for (unsigned e = 0; e < mDesc->mItems.Size(); ++e) + { + auto entry = mDesc->mItems[e]; + entry->mHidden = false; + entry->SetHeight(height); + totalheight += height; + } + if (mDesc->mSpacing <= 0) calculatedentryspacing = std::max(0, (y_lower - y_upper - totalheight) / (numvalidentries > 1 ? numvalidentries - 1 : 1)); + if (calculatedentryspacing <= 0) calculatedentryspacing = mDesc->mSpacing; + + + // totalHeight calculating pass + int totalHeight; + for (unsigned e = 0; e < mDesc->mItems.Size(); ++e) + { + auto entry = mDesc->mItems[e]; + if (!entry->mHidden) + { + entry->SetY(y_upper + y); + y += height; + totalHeight = y; + y += calculatedentryspacing; + } + } + } +}; + +class RedneckMainMenu : public RedneckListMenu +{ + void PreDraw() override + { + RedneckListMenu::PreDraw(); + if (RRRA) + rotatesprite_fs(int(origin.X * 65536) + ((MENU_MARGIN_CENTER - 5) << 16), int(origin.Y * 65536) + ((57) << 16), 16592L, 0, THREEDEE, 0, 0, 10); + else + rotatesprite_fs(int(origin.X * 65536) + ((MENU_MARGIN_CENTER + 5) << 16), int(origin.Y * 65536) + ((24) << 16), 23592L, 0, INGAMEDUKETHREEDEE, 0, 0, 10); + } +}; + +//---------------------------------------------------------------------------- +// +// Menu related game interface functions +// +//---------------------------------------------------------------------------- + +void GameInterface::DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) +{ + int ydim_upper = 0; + int ydim_lower = ydim - 1; + //int32_t const indent = 0; // not set for any relevant menu + int x = int(xpos * 65536); + + uint8_t status = 0; + if (state == NIT_SelectedState) + status |= MT_Selected; + if (state == NIT_InactiveState) + status |= MT_Disabled; + if (flags & LMF_Centered) + status |= MT_XCenter; + + bool const dodraw = true; + MenuFont_t& font = fontnum == NIT_BigFont ? MF_Redfont : fontnum == NIT_SmallFont ? MF_Bluefont : MF_Minifont; + + int32_t const height = font.get_yline(); + status |= MT_YCenter; + int32_t const y_internal = int(ypos * 65536) + ((height >> 17) << 16);// -menu->scrollPos; + + vec2_t textsize; + if (dodraw) + textsize = Menu_Text(x, y_internal, &font, text, status, ydim_upper, ydim_lower); + + if (dodraw && (status & MT_Selected) && state != 1) + { + if (status & MT_XCenter) + { + Menu_DrawCursorLeft(x + font.cursorCenterPosition, y_internal, font.cursorScale); + Menu_DrawCursorRight(x - font.cursorCenterPosition, y_internal, font.cursorScale); + } + else + Menu_DrawCursorLeft(x /*+ indent*/ - font.cursorLeftPosition, y_internal, font.cursorScale); + } + +} + + +void GameInterface::MenuOpened() +{ + S_PauseSounds(true); + if ((!g_netServer && ud.multimode < 2)) + { + ready2send = 0; + totalclock = ototalclock; + screenpeek = myconnectindex; + } + + auto& gm = g_player[myconnectindex].ps->gm; + if (gm & MODE_GAME) + { + gm |= MODE_MENU; + } +} + +void GameInterface::MenuSound(EMenuSounds snd) +{ + switch (snd) + { + case CursorSound: + S_PlaySound(RR ? 335 : KICK_HIT); + break; + + case AdvanceSound: + S_PlaySound(RR? 341 : PISTOL_BODYHIT); + break; + + case CloseSound: + S_PlaySound(EXITMENUSOUND); + break; + + default: + return; + } +} + +void GameInterface::MenuClosed() +{ + + auto& gm = g_player[myconnectindex].ps->gm; + if (gm & MODE_GAME) + { + if (gm & MODE_MENU) + I_ClearAllInput(); + + // The following lines are here so that you cannot close the menu when no game is running. + gm &= ~MODE_MENU; + + if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) + { + ready2send = 1; + totalclock = ototalclock; + CAMERACLOCK = (int32_t)totalclock; + CAMERADIST = 65536; + + // Reset next-viewscreen-redraw counter. + // XXX: are there any other cases like that in need of handling? + if (g_curViewscreen >= 0) + actor[g_curViewscreen].t_data[0] = (int32_t)totalclock; + } + + G_UpdateScreenArea(); + S_PauseSounds(false); + } +} + +bool GameInterface::CanSave() +{ + if (ud.recstat == 2) return false; + auto &myplayer = *g_player[myconnectindex].ps; + if (sprite[myplayer.i].extra <= 0) + { + P_DoQuote(QUOTE_SAVE_DEAD, &myplayer); + return false; + } + return true; +} + +void GameInterface::StartGame(FGameStartup& gs) +{ + int32_t skillsound = PISTOL_BODYHIT; + + switch (gs.Skill) + { + case 0: + skillsound = 427; + break; + case 1: + skillsound = 428; + break; + case 2: + skillsound = 196; + break; + case 3: + skillsound = 195; + break; + case 4: + skillsound = 197; + break; + } + + ud.m_player_skill = gs.Skill + 1; + if (menu_sounds) g_skillSoundVoice = S_PlaySound(skillsound); + ud.m_respawn_monsters = (gs.Skill == 3); + ud.m_monsters_off = ud.monsters_off = 0; + ud.m_respawn_items = 0; + ud.m_respawn_inventory = 0; + ud.multimode = 1; + ud.m_volume_number = gs.Episode; + m_level_number = gs.Level; + G_NewGame_EnterLevel(); + +} + +FSavegameInfo GameInterface::GetSaveSig() +{ + return { SAVESIG_RR, MINSAVEVER_RR, SAVEVER_RR }; +} + +void GameInterface::DrawMenuCaption(const DVector2& origin, const char* text) +{ + Menu_DrawTopBar(origin); + Menu_DrawTopBarCaption(text, origin); +} + +void GameInterface::DrawCenteredTextScreen(const DVector2 &origin, const char *text, int position, bool bg) +{ + if (bg) Menu_DrawBackground(origin); + else + { + // Only used for the confirmation screen. + int lines = 1; + for (int i = 0; text[i]; i++) if (text[i] == '\n') lines++; + int height = lines * Menu_GetFontHeight(NIT_SmallFont); + position -= height >> 17; + } + G_ScreenText(MF_Bluefont.tilenum, int((origin.X + 160) * 65536), int((origin.Y + position) * 65536), MF_Bluefont.zoom, 0, 0, text, 0, MF_Bluefont.pal, + 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, + MF_Bluefont.textflags | TEXT_XCENTER, 0, 0, xdim - 1, ydim - 1); +} + + +void GameInterface::DrawPlayerSprite(const DVector2& origin, bool onteam) +{ + if (RR) + rotatesprite_fs(int(origin.X * 65536) + (260<<16), int(origin.Y * 65536) + ((24+(tilesiz[APLAYER].y>>2))<<16), 24576L,0,3845+36-((((8-((int32_t) totalclock>>4)))&7)*5),0,onteam ? G_GetTeamPalette(playerteam) : G_CheckPlayerColor(playercolor),10); + else + rotatesprite_fs(int(origin.X * 65536) + (260<<16), int(origin.Y * 65536) + ((24+(tilesiz[APLAYER].y>>1))<<16), 49152L,0,1441-((((4-((int32_t) totalclock>>4)))&3)*5),0,onteam ? G_GetTeamPalette(playerteam) : G_CheckPlayerColor(playercolor),10); +} + +void GameInterface::QuitToTitle() +{ + g_player[myconnectindex].ps->gm = MODE_DEMO; + if (ud.recstat == 1) + G_CloseDemoWrite(); + artClearMapArt(); +} + +END_RR_NS + +//---------------------------------------------------------------------------- +// +// Class registration +// +//---------------------------------------------------------------------------- + + +static TMenuClassDescriptor _mm("Redneck.MainMenu"); +static TMenuClassDescriptor _lm("Redneck.ListMenu"); + +void RegisterRedneckMenus() +{ + menuClasses.Push(&_mm); + menuClasses.Push(&_lm); +} diff --git a/source/rr/src/demo.cpp b/source/rr/src/demo.cpp index 1ca20b462..8dd553223 100644 --- a/source/rr/src/demo.cpp +++ b/source/rr/src/demo.cpp @@ -55,12 +55,12 @@ static int32_t demorec_seeds=1, demo_hasseeds; static void Demo_RestoreModes(int32_t menu) { - if (menu) - Menu_Open(myconnectindex); - else - Menu_Close(myconnectindex); + if (menu) + M_StartControlPanel(false); + else + M_ClearMenus(); - g_player[myconnectindex].ps->gm &= ~MODE_GAME; + g_player[myconnectindex].ps->gm &= ~MODE_GAME; g_player[myconnectindex].ps->gm |= MODE_DEMO; } @@ -95,8 +95,7 @@ static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine demofnptr = demofn; } - g_demo_recFilePtr = fopenFileReader(demofnptr, g_loadFromGroupOnly); - if (!g_demo_recFilePtr.isOpen()) + if (!g_demo_recFilePtr.OpenFile(demofnptr)) return 0; Bassert(g_whichDemo >= 1); @@ -110,7 +109,7 @@ static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine demo_hasdiffs = saveh.recdiffsp; g_demo_totalCnt = saveh.reccnt; - demo_hasseeds = saveh.synccompress&2; + demo_hasseeds = 0; i = g_demo_totalCnt/REALGAMETICSPERSEC; OSD_Printf("demo %d duration: %d min %d sec\n", g_whichDemo, i/60, i%60); @@ -143,7 +142,7 @@ void G_OpenDemoWrite(void) if ((g_player[myconnectindex].ps->gm&MODE_GAME) && g_player[myconnectindex].ps->dead_flag) { - Bstrcpy(apStrings[QUOTE_RESERVED4], "CANNOT START DEMO RECORDING WHEN DEAD!"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "CANNOT START DEMO RECORDING WHEN DEAD!"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); ud.recstat = m_recstat = 0; return; @@ -173,14 +172,13 @@ void G_OpenDemoWrite(void) if (g_demo_filePtr == NULL) return; - i=sv_saveandmakesnapshot(*g_demo_filePtr, nullptr, -1, demorec_diffs_cvar, demorec_diffcompress_cvar, - (demorec_seeds_cvar<<1)); + i=sv_saveandmakesnapshot(*g_demo_filePtr, nullptr, -1, (demorec_seeds_cvar<<1)); if (i) { delete g_demo_filePtr; g_demo_filePtr = nullptr; error_wopen_demo: - Bstrcpy(apStrings[QUOTE_RESERVED4], "FAILED STARTING DEMO RECORDING. SEE CONSOLE FOR DETAILS."); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "FAILED STARTING DEMO RECORDING. SEE CONSOLE FOR DETAILS."); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); ud.recstat = m_recstat = 0; return; @@ -190,7 +188,7 @@ error_wopen_demo: demorec_diffs = demorec_diffs_cvar; demorec_difftics = demorec_difftics_cvar; - Bsprintf(apStrings[QUOTE_RESERVED4], "DEMO %d RECORDING STARTED", demonum-1); + quoteMgr.FormatQuote(QUOTE_RESERVED4, "DEMO %d RECORDING STARTED", demonum-1); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); ud.reccnt = 0; @@ -285,7 +283,7 @@ void G_CloseDemoWrite(void) sv_freemem(); - Bstrcpy(apStrings[QUOTE_RESERVED4], "DEMO RECORDING STOPPED"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "DEMO RECORDING STOPPED"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); } #if KRANDDEBUG @@ -489,7 +487,7 @@ RECHECK: fadepal(0,0,0, 0,252,28); P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1); // JBF 20040308 G_DrawBackground(); - M_DisplayMenus(); + //M_DisplayMenus(); videoNextPage(); fadepal(0,0,0, 252,0,-28); ud.reccnt = 0; @@ -523,8 +521,8 @@ RECHECK: { FX_StopAllSounds(); S_ClearSoundLocks(); - Menu_Open(myconnectindex); - } + M_StartControlPanel(false); + } ready2send = 0; bigi = 0; @@ -664,7 +662,7 @@ RECHECK: corrupt: OSD_Printf(OSD_ERROR "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode); nextdemo: - Menu_Open(myconnectindex); + M_StartControlPanel(false); nextdemo_nomenu: foundemo = 0; ud.reccnt = 0; @@ -852,7 +850,7 @@ nextdemo_nomenu: Net_GetPackets(); if (g_player[myconnectindex].gotvote == 0 && voting != -1 && voting != myconnectindex) - gametext_center(60, "Press F1 to Accept, F2 to Decline"); + gametext_center(60, GStrings("TXT_PRESSF1_F2")); } if ((g_player[myconnectindex].ps->gm&MODE_MENU) && (g_player[myconnectindex].ps->gm&MODE_EOL)) @@ -862,16 +860,6 @@ nextdemo_nomenu: goto RECHECK; } - if (I_EscapeTrigger() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && (g_player[myconnectindex].ps->gm&MODE_TYPE) == 0) - { - I_EscapeTriggerClear(); - FX_StopAllSounds(); - S_ClearSoundLocks(); - Menu_Open(myconnectindex); - Menu_Change(MENU_MAIN); - S_MenuSound(); - } - if (Demo_IsProfiling()) { // Do nothing: sampletimer() is reached from M_DisplayMenus() -> @@ -884,15 +872,15 @@ nextdemo_nomenu: if ((g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE) { g_player[myconnectindex].ps->gm = 0; - Menu_Open(myconnectindex); - } + M_StartControlPanel(false); + } } else { - if (ud.recstat != 2) - M_DisplayMenus(); + //if (ud.recstat != 2) + //M_DisplayMenus(); - if ((g_netServer || ud.multimode > 1) && !Menu_IsTextInput(m_currentMenu)) + if ((g_netServer || ud.multimode > 1))// && !Menu_IsTextInput(m_currentMenu)) { ControlInfo noshareinfo; CONTROL_GetInput(&noshareinfo); diff --git a/source/rr/src/duke3d.h b/source/rr/src/duke3d.h index 4b3e27367..d64e30770 100644 --- a/source/rr/src/duke3d.h +++ b/source/rr/src/duke3d.h @@ -36,6 +36,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "polymost.h" #include "gamecvars.h" +#include "menu/menu.h" BEGIN_RR_NS @@ -60,7 +61,6 @@ BEGIN_RR_NS #define MOVEFIFOSIZ 256 // KEEPINSYNC lunatic/con_lang.lua -#define MAXVOLUMES 7 #define MAXLEVELS 64 #define MAXGAMETYPES 16 @@ -155,9 +155,22 @@ struct GameInterface : ::GameInterface bool validate_hud(int) override; void set_hud_layout(int size) override; void set_hud_scale(int size) override; - bool mouseInactiveConditional(bool condition) override; FString statFPS() override; GameStats getStats() override; + void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags); + void MenuOpened() override; + void MenuSound(EMenuSounds snd) override; + void MenuClosed() override; + bool CanSave() override; + void StartGame(FGameStartup& gs) override; + FSavegameInfo GetSaveSig() override; + void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) override; + void DrawMenuCaption(const DVector2& origin, const char* text) override; + bool SaveGame(FSaveGameNode*) override; + bool LoadGame(FSaveGameNode*) override; + void DoPrintMessage(int prio, const char* text) override; + void DrawPlayerSprite(const DVector2& origin, bool onteam) override; + void QuitToTitle() override; }; END_RR_NS diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index 3ed55ff05..d7b1a3336 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -46,6 +46,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "m_argv.h" #include "filesystem/filesystem.h" #include "statistics.h" +#include "c_dispatch.h" +#include "mapinfo.h" // Uncomment to prevent anything except mirrors from drawing. It is sensible to // also uncomment ENGINE_CLEAR_SCREEN in build/src/engine_priv.h. @@ -77,7 +79,7 @@ int32_t g_quitDeadline = 0; int32_t g_cameraDistance = 0, g_cameraClock = 0; static int32_t g_quickExit; -char boardfilename[BMAX_PATH] = {0}, currentboardfilename[BMAX_PATH] = {0}; +char boardfilename[BMAX_PATH] = {0}; int32_t voting = -1; int32_t vote_map = -1, vote_episode = -1; @@ -108,14 +110,14 @@ const char *G_DefaultRtsFile(void) return defaultrtsfilename[GAME_DUKE]; else if (NAPALM) { - if (!testkopen(defaultrtsfilename[GAME_NAPALM],0) && testkopen(defaultrtsfilename[GAME_NAM],0)) + if (!fileSystem.FileExists(defaultrtsfilename[GAME_NAPALM]) && fileSystem.FileExists(defaultrtsfilename[GAME_NAM])) return defaultrtsfilename[GAME_NAM]; // NAM/NAPALM Sharing else return defaultrtsfilename[GAME_NAPALM]; } else if (NAM) { - if (!testkopen(defaultrtsfilename[GAME_NAM],0) && testkopen(defaultrtsfilename[GAME_NAPALM],0)) + if (!fileSystem.FileExists(defaultrtsfilename[GAME_NAM]) && fileSystem.FileExists(defaultrtsfilename[GAME_NAPALM])) return defaultrtsfilename[GAME_NAPALM]; // NAM/NAPALM Sharing else return defaultrtsfilename[GAME_NAM]; @@ -183,13 +185,6 @@ void G_HandleSpecialKeys(void) G_UpdateScreenArea(); } - if (inputState.UnboundKeyPressed(sc_F12)) - { - inputState.ClearKeyStatus(sc_F12); - videoCaptureScreen(); - P_DoQuote(QUOTE_SCREEN_SAVED, g_player[myconnectindex].ps); - } - // only dispatch commands here when not in a game if (!(g_player[myconnectindex].ps->gm & MODE_GAME)) OSD_DispatchQueued(); @@ -5963,12 +5958,6 @@ extern int G_StartRTS(int lumpNum, int localPlayer) return 0; } -void G_PrintCurrentMusic(void) -{ - Bsnprintf(apStrings[QUOTE_MUSIC], MAXQUOTELEN, "Playing %s", g_mapInfo[g_musicIndex].musicfn); - P_DoQuote(QUOTE_MUSIC, g_player[myconnectindex].ps); -} - // Trying to sanitize the mess of options and the mess of variables the mess was stored in. (Did I say this was a total mess before...? >) ) // Hopefully this is more comprehensible, at least it neatly stores everything useful in a single linear value... bool GameInterface::validate_hud(int layout) @@ -6032,7 +6021,7 @@ void G_HandleLocalKeys(void) { if (inputState.UnboundKeyPressed(sc_F1) || inputState.UnboundKeyPressed(sc_F2) || cl_autovote) { - G_AddUserQuote("Vote Cast"); + G_AddUserQuote(GStrings("VoteCast")); Net_SendMapVote(inputState.UnboundKeyPressed(sc_F1) || cl_autovote ? cl_autovote-1 : 0); inputState.ClearKeyStatus(sc_F1); inputState.ClearKeyStatus(sc_F2); @@ -6213,24 +6202,6 @@ void G_HandleLocalKeys(void) { if (SHIFTS_IS_PRESSED) { - if (ridiculeNum == 5 && g_player[myconnectindex].ps->fta > 0 && g_player[myconnectindex].ps->ftq == QUOTE_MUSIC) - { - const unsigned int maxi = VOLUMEALL ? MUS_FIRST_SPECIAL : 6; - - unsigned int MyMusicIndex = g_musicIndex; - do - { - ++MyMusicIndex; - if (MyMusicIndex >= maxi) - MyMusicIndex = 0; - } - while (S_TryPlayLevelMusic(MyMusicIndex)); - - G_PrintCurrentMusic(); - - return; - } - G_AddUserQuote(*CombatMacros[ridiculeNum-1]); Net_SendTaunt(ridiculeNum); pus = NUMPAGES; @@ -6261,135 +6232,7 @@ void G_HandleLocalKeys(void) typebuf[0] = 0; } - if (inputState.UnboundKeyPressed(sc_F1)/* || (ud.show_help && I_AdvanceTrigger())*/) - { - inputState.ClearKeyStatus(sc_F1); - Menu_Change(MENU_STORY); - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2)) - { - ready2send = 0; - totalclock = ototalclock; - screenpeek = myconnectindex; - } - } - - // if((!net_server && ud.multimode < 2)) - { - if (ud.recstat != 2 && (!RRRA || ud.player_skill != 4) && (!RR || RRRA || ud.player_skill != 5) && inputState.UnboundKeyPressed(sc_F2)) - { - inputState.ClearKeyStatus(sc_F2); - -FAKE_F2: - if (sprite[g_player[myconnectindex].ps->i].extra <= 0) - { - P_DoQuote(QUOTE_SAVE_DEAD,g_player[myconnectindex].ps); - return; - } - - Menu_Change(MENU_SAVE); - - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2)) - { - ready2send = 0; - totalclock = ototalclock; - screenpeek = myconnectindex; - } - } - - if ((!RRRA || ud.player_skill != 4) && (!RR || RRRA || ud.player_skill != 5) && inputState.UnboundKeyPressed(sc_F3)) - { - inputState.ClearKeyStatus(sc_F3); - -FAKE_F3: - Menu_Change(MENU_LOAD); - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 0; - totalclock = ototalclock; - } - - screenpeek = myconnectindex; - } - } - - if (inputState.UnboundKeyPressed(sc_F4)) - { - inputState.ClearKeyStatus(sc_F4); - - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 0; - totalclock = ototalclock; - } - - Menu_Change(MENU_SOUND_INGAME); - } - - if (inputState.UnboundKeyPressed(sc_F5) && MusicEnabled()) - { - map_t *const pMapInfo = &g_mapInfo[g_musicIndex]; - char *const musicString = apStrings[QUOTE_MUSIC]; - - inputState.ClearKeyStatus(sc_F5); - - if (pMapInfo->musicfn != NULL) - Bsnprintf(musicString, MAXQUOTELEN, "%s. Use SHIFT-F5 to change.", pMapInfo->musicfn); - else - musicString[0] = '\0'; - - P_DoQuote(QUOTE_MUSIC, g_player[myconnectindex].ps); - } - - if ((buttonMap.ButtonDown(gamefunc_Quick_Save) || g_doQuickSave == 1) && (!RRRA || ud.player_skill != 4) && (!RR || RRRA || ud.player_skill != 5) && (g_player[myconnectindex].ps->gm&MODE_GAME)) - { - buttonMap.ClearButton(gamefunc_Quick_Save); - - g_doQuickSave = 0; - - if (!g_lastusersave.isValid()) - goto FAKE_F2; - - inputState.keyFlushChars(); - - if (sprite[g_player[myconnectindex].ps->i].extra <= 0) - { - P_DoQuote(QUOTE_SAVE_DEAD,g_player[myconnectindex].ps); - return; - } - - g_screenCapture = 1; - G_DrawRooms(myconnectindex,65536); - g_screenCapture = 0; - - if (g_lastusersave.isValid()) - { - savebrief_t & sv = g_lastusersave; - - // dirty hack... char 127 in last position indicates an auto-filled name - if (sv.name[MAXSAVEGAMENAME] == 127) - { - strncpy(sv.name, g_mapInfo[ud.volume_number * MAXLEVELS + ud.level_number].name, MAXSAVEGAMENAME); - sv.name[MAXSAVEGAMENAME] = 127; - } - - g_quickload = &sv; - G_SavePlayerMaybeMulti(sv); - } - } - if (buttonMap.ButtonDown(gamefunc_Third_Person_View)) { buttonMap.ClearButton(gamefunc_Third_Person_View); @@ -6405,64 +6248,6 @@ FAKE_F3: } } - if (inputState.UnboundKeyPressed(sc_F8)) - { - inputState.ClearKeyStatus(sc_F8); - - int const fta = !hud_messages; - hud_messages = 1; - P_DoQuote(fta ? QUOTE_MESSAGES_ON : QUOTE_MESSAGES_OFF, g_player[myconnectindex].ps); - hud_messages = fta; - } - - if ((buttonMap.ButtonDown(gamefunc_Quick_Load) || g_doQuickSave == 2) && (!RRRA || ud.player_skill != 4) && (!RR || RRRA || ud.player_skill != 5) && (g_player[myconnectindex].ps->gm&MODE_GAME)) - { - buttonMap.ClearButton(gamefunc_Quick_Load); - - g_doQuickSave = 0; - - if (g_quickload == nullptr || !g_quickload->isValid()) - goto FAKE_F3; - else if (g_quickload->isValid()) - { - inputState.keyFlushChars(); - inputState.ClearKeysDown(); - S_PauseSounds(true); - if (G_LoadPlayerMaybeMulti(*g_quickload) != 0) - g_quickload->reset(); - } - } - - if (inputState.UnboundKeyPressed(sc_F10)) - { - inputState.ClearKeyStatus(sc_F10); - - Menu_Change(MENU_QUIT_INGAME); - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 0; - totalclock = ototalclock; - } - } - - if (inputState.UnboundKeyPressed(sc_F11)) - { - inputState.ClearKeyStatus(sc_F11); - - Menu_Change(MENU_COLCORR_INGAME); - S_PauseSounds(true); - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 0; - totalclock = ototalclock; - } - } - if (ud.overhead_on != 0) { int const timerOffset = ((int) totalclock - nonsharedtimer); @@ -6487,13 +6272,6 @@ FAKE_F3: G_UpdateScreenArea(); } - if (buttonMap.ButtonDown(gamefunc_AutoRun)) - { - buttonMap.ClearButton(gamefunc_AutoRun); - cl_autorun = !cl_autorun; - P_DoQuote(QUOTE_RUN_MODE_OFF+cl_autorun,g_player[myconnectindex].ps); - } - if (buttonMap.ButtonDown(gamefunc_Map)) { buttonMap.ClearButton(gamefunc_Map); @@ -6589,8 +6367,8 @@ static int32_t S_DefineMusic(const char *ID, const char *name) if (sel < 0) return -1; } - - return S_DefineAudioIfSupported(&g_mapInfo[sel].musicfn, name); + mapList[sel].music = name; + return 0; } static int parsedefinitions_game(scriptfile *, int); @@ -6821,7 +6599,7 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) break; } - if (fileName == NULL || check_file_exist(fileName)) + if (fileName == NULL || fileSystem.FileExists(fileName)) break; if (S_DefineMusic(musicID, fileName) == -1) @@ -6969,7 +6747,7 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) break; } - if (fileName == NULL || check_file_exist(fileName)) + if (fileName == NULL || fileSystem.FileExists(fileName)) break; // maybe I should have just packed this into a sound_t and passed a reference... @@ -7021,19 +6799,9 @@ static void G_Cleanup(void) for (i=(MAXLEVELS*(MAXVOLUMES+1))-1; i>=0; i--) // +1 volume for "intro", "briefing" music { - Bfree(g_mapInfo[i].name); - Bfree(g_mapInfo[i].filename); - Bfree(g_mapInfo[i].musicfn); - G_FreeMapState(i); } - for (i=MAXQUOTES-1; i>=0; i--) - { - Bfree(apStrings[i]); - Bfree(apXStrings[i]); - } - for (i=MAXPLAYERS-1; i>=0; i--) { Bfree(g_player[i].ps); @@ -7068,7 +6836,6 @@ static void G_Cleanup(void) void G_Shutdown(void) { S_SoundShutdown(); - S_MusicShutdown(); CONTROL_Shutdown(); G_SetFog(0); engineUnInit(); @@ -7327,49 +7094,35 @@ static void G_Startup(void) if (userConfig.CommandMap.IsNotEmpty()) { + FString startupMap; if (VOLUMEONE) { initprintf("The -map option is available in the registered version only!\n"); - boardfilename[0] = 0; } else { - char *dot, *slash; + startupMap = userConfig.CommandMap; + if (startupMap.IndexOfAny("/\\") < 0) startupMap.Insert(0, "/"); + DefaultExtension(startupMap, ".map"); + startupMap.Substitute("\\", "/"); + NormalizeFileName(startupMap); - boardfilename[0] = '/'; - boardfilename[1] = 0; - Bstrcat(boardfilename, userConfig.CommandMap); - - dot = Bstrrchr(boardfilename,'.'); - slash = Bstrrchr(boardfilename,'/'); - if (!slash) slash = Bstrrchr(boardfilename,'\\'); - - if ((!slash && !dot) || (slash && dot < slash)) - Bstrcat(boardfilename,".map"); - - Bcorrectfilename(boardfilename,0); - - if (testkopen(boardfilename, 0)) - { - initprintf("Using level: \"%s\".\n",boardfilename); + if (fileSystem.FileExists(startupMap)) + { + initprintf("Using level: \"%s\".\n",startupMap.GetChars()); } else { - initprintf("Level \"%s\" not found.\n",boardfilename); + initprintf("Level \"%s\" not found.\n",startupMap.GetChars()); boardfilename[0] = 0; } } + strncpy(boardfilename, startupMap, BMAX_PATH); } for (i=0; i 1) @@ -7392,7 +7145,7 @@ static void P_SetupMiscInputSettings(void) { DukePlayer_t *ps = g_player[myconnectindex].ps; - ps->aim_mode = in_aimmode; + ps->aim_mode = in_mousemode; ps->auto_aim = cl_autoaim; ps->weaponswitch = cl_weaponswitch; } @@ -7413,7 +7166,7 @@ void G_UpdatePlayerFromMenu(void) /*int32_t j = g_player[myconnectindex].ps->team;*/ P_SetupMiscInputSettings(); - g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = playercolor; + g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = G_CheckPlayerColor(playercolor); g_player[myconnectindex].pteam = playerteam; @@ -7428,14 +7181,14 @@ void G_BackToMenu(void) if (ud.recstat == 1) G_CloseDemoWrite(); ud.warp_on = 0; g_player[myconnectindex].ps->gm = 0; - Menu_Open(myconnectindex); - Menu_Change(MENU_MAIN); - inputState.keyFlushChars(); + M_StartControlPanel(false); + M_SetMenu(NAME_MainMenu); + inputState.keyFlushChars(); } static int G_EndOfLevel(void) { - STAT_Update(ud.eog); + STAT_Update(ud.eog || (currentLevel->flags & MI_FORCEEOG)); P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0); P_UpdateScreenPal(g_player[myconnectindex].ps); @@ -7465,7 +7218,7 @@ static int G_EndOfLevel(void) // Clear potentially loaded per-map ART only after the bonus screens. artClearMapArt(); - if (ud.eog) + if (ud.eog || (currentLevel->flags & MI_FORCEEOG)) { ud.eog = 0; if ((!g_netServer && ud.multimode < 2)) @@ -7473,9 +7226,7 @@ static int G_EndOfLevel(void) if (!VOLUMEALL) G_DoOrderScreen(); g_player[myconnectindex].ps->gm = 0; - Menu_Open(myconnectindex); - Menu_Change(MENU_MAIN); - return 2; + return 2; } else { @@ -7562,7 +7313,7 @@ int GameInterface::app_main() g_Shareware = 1; else { - if (testkopen("DUKESW.BIN",1)) // JBF 20030810 + if (fileSystem.FileExists("DUKESW.BIN")) // JBF 20030810 { g_Shareware = 1; } @@ -7616,15 +7367,13 @@ int GameInterface::app_main() for (int i=1, j=numplayers; jteam = g_player[j].pteam = i; g_player[j].ps->weaponswitch = 3; g_player[j].ps->auto_aim = 0; i = 1-i; } - if (quitevent) return 4; - Anim_Init(); const char *defsfile = G_DefFile(); @@ -7730,7 +7479,6 @@ int GameInterface::app_main() } videoSetPalette(0, g_player[myconnectindex].ps->palette, 0); - S_MusicStartup(); S_SoundStartup(); } @@ -7767,8 +7515,6 @@ MAIN_LOOP_RESTART: for (int & q : user_quote_time) q = 0; - Menu_Change(MENU_MAIN); - //if (g_networkMode != NET_DEDICATED_SERVER) { G_GetCrosshairColor(); @@ -7807,7 +7553,9 @@ MAIN_LOOP_RESTART: //if (g_networkMode != NET_DEDICATED_SERVER) { - if (G_PlaybackDemo()) + M_StartControlPanel(false); + M_SetMenu(NAME_MainMenu); + if (G_PlaybackDemo()) { FX_StopAllSounds(); g_noLogoAnim = 1; @@ -7827,7 +7575,7 @@ MAIN_LOOP_RESTART: g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = G_GetTeamPalette(g_player[myconnectindex].pteam); else { - if (playercolor) g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = playercolor; + if (playercolor) g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = G_CheckPlayerColor(playercolor); else g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor; } @@ -7836,11 +7584,12 @@ MAIN_LOOP_RESTART: do //main loop { - if (handleevents() && quitevent) - { - inputState.SetKeyStatus(sc_Escape, 1); - quitevent = 0; - } + handleevents(); + if (g_player[myconnectindex].ps->gm == MODE_DEMO) + { + M_ClearMenus(); + goto MAIN_LOOP_RESTART; + } Net_GetPackets(); @@ -7882,8 +7631,6 @@ MAIN_LOOP_RESTART: do { - timerUpdate(); - if (ready2send == 0) break; Net_GetInput(); @@ -7897,8 +7644,6 @@ MAIN_LOOP_RESTART: G_MoveLoop(); } - timerUpdate(); - if (totalclock - moveClock >= TICSPERFRAME) { // computing a tic takes longer than a tic, so we're slowing @@ -7931,7 +7676,7 @@ MAIN_LOOP_RESTART: { idle(); } - else */if (G_FPSLimit() || g_saveRequested) + else */if (G_FPSLimit()) { int const smoothRatio = calc_smoothratio(totalclock, ototalclock); @@ -7947,24 +7692,6 @@ MAIN_LOOP_RESTART: } } - // handle CON_SAVE and CON_SAVENN - if (g_saveRequested) - { - inputState.keyFlushChars(); - videoNextPage(); - - g_screenCapture = 1; - G_DrawRooms(myconnectindex, 65536); - g_screenCapture = 0; - - G_SavePlayerMaybeMulti(g_lastautosave, true); - g_quickload = &g_lastautosave; - - OSD_Printf("Saved: %s\n", g_lastautosave.path); - - g_saveRequested = false; - } - if (g_player[myconnectindex].ps->gm&MODE_DEMO) goto MAIN_LOOP_RESTART; } @@ -8049,7 +7776,7 @@ int G_DoMoveThings(void) { if (ldist(&sprite[pPlayer->i], &sprite[hitData.sprite]) < 9216) { - Bsprintf(apStrings[QUOTE_RESERVED3], "%s", &g_player[playerNum].user_name[0]); + quoteMgr.FormatQuote(QUOTE_RESERVED3, "%s", &g_player[playerNum].user_name[0]); pPlayer->fta = 12, pPlayer->ftq = QUOTE_RESERVED3; } } diff --git a/source/rr/src/game.h b/source/rr/src/game.h index 75f91f351..cc4d938f0 100644 --- a/source/rr/src/game.h +++ b/source/rr/src/game.h @@ -163,8 +163,6 @@ typedef struct { int32_t playerbest; - int32_t default_volume, default_skill; - //int32_t returnvar[MAX_RETURN_VALUES-1]; uint32_t userbytever; @@ -200,7 +198,7 @@ extern user_defs ud; // this is checked against http://eduke32.com/VERSION extern const char *s_buildDate; -extern char boardfilename[BMAX_PATH], currentboardfilename[BMAX_PATH]; +extern char boardfilename[BMAX_PATH]; static inline int G_HaveUserMap(void) { @@ -309,7 +307,7 @@ void fadepal(int32_t r,int32_t g,int32_t b,int32_t start,int32_t end,int32_t ste //void fadepaltile(int32_t r,int32_t g,int32_t b,int32_t start,int32_t end,int32_t step,int32_t tile); void G_InitTimer(int32_t ticspersec); -static inline int32_t G_GetTeamPalette(int32_t team) +inline int32_t G_GetTeamPalette(int32_t team) { int8_t pal[] = { 3, 10, 11, 12 }; @@ -476,7 +474,6 @@ static inline int G_GetViewscreenSizeShift(const uspritetype *tspr) #endif } -extern void G_PrintCurrentMusic(void); EXTERN_INLINE_HEADER void G_SetStatusBarScale(int32_t sc); diff --git a/source/rr/src/gamedef.cpp b/source/rr/src/gamedef.cpp index 992076693..219c23bac 100644 --- a/source/rr/src/gamedef.cpp +++ b/source/rr/src/gamedef.cpp @@ -35,6 +35,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "osd.h" #include "m_crc32.h" #include "printf.h" +#include "menu/menu.h" +#include "stringtable.h" +#include "mapinfo.h" BEGIN_RR_NS @@ -778,7 +781,7 @@ static int32_t C_CheckEmptyBranch(int32_t tw, intptr_t lastScriptPtr) static void C_Include(const char *confile) { - auto fp = kopenFileReader(confile,0); + auto fp = fileSystem.OpenFileReader(confile,0); if (!fp.isOpen()) { @@ -884,141 +887,45 @@ void C_DefineMusic(int volumeNum, int levelNum, const char *fileName) Bassert((unsigned)volumeNum < MAXVOLUMES+1); Bassert((unsigned)levelNum < MAXLEVELS); - map_t *const pMapInfo = &g_mapInfo[(MAXLEVELS*volumeNum)+levelNum]; - - Bfree(pMapInfo->musicfn); - pMapInfo->musicfn = dup_filename(fileName); + mapList[(MAXLEVELS*volumeNum)+levelNum].music = fileName; } void C_DefineVolumeFlags(int32_t vol, int32_t flags) { Bassert((unsigned)vol < MAXVOLUMES); - g_volumeFlags[vol] = flags; + gVolumeFlags[vol] = flags; } int32_t C_AllocQuote(int32_t qnum) { Bassert((unsigned)qnum < MAXQUOTES); - - if (apStrings[qnum] == NULL) - { - apStrings[qnum] = (char *)Xcalloc(MAXQUOTELEN,sizeof(uint8_t)); - return 1; - } - - return 0; + return 1; } -#ifndef EDUKE32_TOUCH_DEVICES -static void C_ReplaceQuoteSubstring(const size_t q, char const * const query, char const * const replacement) -{ - size_t querylength = Bstrlen(query); - - for (bssize_t i = MAXQUOTELEN - querylength - 2; i >= 0; i--) - if (Bstrncmp(&apStrings[q][i], query, querylength) == 0) - { - Bmemset(tempbuf, 0, sizeof(tempbuf)); - Bstrncpy(tempbuf, apStrings[q], i); - Bstrcat(tempbuf, replacement); - Bstrcat(tempbuf, &apStrings[q][i + querylength]); - Bstrncpy(apStrings[q], tempbuf, MAXQUOTELEN - 1); - i = MAXQUOTELEN - querylength - 2; - } -} -#endif - void C_InitQuotes(void) { - for (bssize_t i = 0; i < 128; i++) C_AllocQuote(i); - -#ifdef EDUKE32_TOUCH_DEVICES - apStrings[QUOTE_DEAD] = 0; -#else - char const * OpenGameFunc = buttonMap.GetButtonName(gamefunc_Open); - C_ReplaceQuoteSubstring(QUOTE_DEAD, "SPACE", OpenGameFunc); - C_ReplaceQuoteSubstring(QUOTE_DEAD, "OPEN", OpenGameFunc); - C_ReplaceQuoteSubstring(QUOTE_DEAD, "USE", OpenGameFunc); +#if 0 // if we want to keep this it must be done differently. This does not play nice with text substitution. + auto openkeys = Bindings.GetKeysForCommand("+open"); + if (openkeys.Size()) + { + auto OpenGameFunc = C_NameKeys(openkeys.Data(), 1); + quoteMgr.Substitute(QUOTE_DEAD, "SPACE", OpenGameFunc); + quoteMgr.Substitute(QUOTE_DEAD, "OPEN", OpenGameFunc); + quoteMgr.Substitute(QUOTE_DEAD, "USE", OpenGameFunc); + } #endif - // most of these are based on Blood, obviously - const char *PlayerObituaries[] = - { - "^02%s^02 beat %s^02 like a cur", - "^02%s^02 broke %s", - "^02%s^02 body bagged %s", - "^02%s^02 boned %s^02 like a fish", - "^02%s^02 castrated %s", - "^02%s^02 creamed %s", - "^02%s^02 crushed %s", - "^02%s^02 destroyed %s", - "^02%s^02 diced %s", - "^02%s^02 disemboweled %s", - "^02%s^02 erased %s", - "^02%s^02 eviscerated %s", - "^02%s^02 flailed %s", - "^02%s^02 flattened %s", - "^02%s^02 gave AnAl MaDnEsS to %s", - "^02%s^02 gave %s^02 Anal Justice", - "^02%s^02 hosed %s", - "^02%s^02 hurt %s^02 real bad", - "^02%s^02 killed %s", - "^02%s^02 made dog meat out of %s", - "^02%s^02 made mincemeat out of %s", - "^02%s^02 manhandled %s", - "^02%s^02 massacred %s", - "^02%s^02 mutilated %s", - "^02%s^02 murdered %s", - "^02%s^02 neutered %s", - "^02%s^02 punted %s", - "^02%s^02 reamed %s", - "^02%s^02 ripped %s^02 a new orifice", - "^02%s^02 rocked %s", - "^02%s^02 sent %s^02 to hell", - "^02%s^02 shredded %s", - "^02%s^02 slashed %s", - "^02%s^02 slaughtered %s", - "^02%s^02 sliced %s", - "^02%s^02 smacked %s around", - "^02%s^02 smashed %s", - "^02%s^02 snuffed %s", - "^02%s^02 sodomized %s", - "^02%s^02 splattered %s", - "^02%s^02 sprayed %s", - "^02%s^02 squashed %s", - "^02%s^02 throttled %s", - "^02%s^02 toasted %s", - "^02%s^02 vented %s", - "^02%s^02 ventilated %s", - "^02%s^02 wasted %s", - "^02%s^02 wrecked %s", - }; - - const char *PlayerSelfObituaries[] = - { - "^02%s^02 is excrement", - "^02%s^02 is hamburger", - "^02%s^02 suffered scrotum separation", - "^02%s^02 volunteered for population control", - "^02%s^02 has suicided", - "^02%s^02 bled out", - }; - - EDUKE32_STATIC_ASSERT(OBITQUOTEINDEX + ARRAY_SIZE(PlayerObituaries)-1 < MAXQUOTES); - EDUKE32_STATIC_ASSERT(SUICIDEQUOTEINDEX + ARRAY_SIZE(PlayerSelfObituaries)-1 < MAXQUOTES); - - g_numObituaries = ARRAY_SIZE(PlayerObituaries); + g_numObituaries = 48; for (bssize_t i = g_numObituaries - 1; i >= 0; i--) { - if (C_AllocQuote(i + OBITQUOTEINDEX)) - Bstrcpy(apStrings[i + OBITQUOTEINDEX], PlayerObituaries[i]); + quoteMgr.FormatQuote(i + OBITQUOTEINDEX, "$TXT_OBITUARY%d", i + 1); } - g_numSelfObituaries = ARRAY_SIZE(PlayerSelfObituaries); + g_numSelfObituaries = 6; for (bssize_t i = g_numSelfObituaries - 1; i >= 0; i--) { - if (C_AllocQuote(i + SUICIDEQUOTEINDEX)) - Bstrcpy(apStrings[i + SUICIDEQUOTEINDEX], PlayerSelfObituaries[i]); + quoteMgr.FormatQuote(i + SUICIDEQUOTEINDEX, "$TXT_SELFOBIT%d", i + 1); } } @@ -1884,23 +1791,10 @@ static int32_t C_ParseCommand(int32_t loop) continue; } - i = 0; - - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - g_volumeNames[j][i] = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= (signed)sizeof(g_volumeNames[j])-1)) - { - initprintf("%s:%d: warning: truncating volume name to %d characters.\n", - g_scriptFileName,g_lineNumber,(int32_t)sizeof(g_volumeNames[j])-1); - g_warningCnt++; - C_NextLine(); - break; - } - } + i = strcspn(textptr, "\r\n"); + gVolumeNames[j] = FStringTable::MakeMacro(textptr, i); + textptr+=i; g_volumeCnt = j+1; - g_volumeNames[j][i] = '\0'; continue; case CON_DEFINESKILLNAME: @@ -1921,26 +1815,12 @@ static int32_t C_ParseCommand(int32_t loop) continue; } - i = 0; - - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - g_skillNames[j][i] = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= (signed)sizeof(g_skillNames[j])-1)) - { - initprintf("%s:%d: warning: truncating skill name to %d characters.\n", - g_scriptFileName,g_lineNumber,(int32_t)sizeof(g_skillNames[j])-1); - g_warningCnt++; - C_NextLine(); - break; - } - } - - g_skillNames[j][i] = '\0'; + i = strcspn(textptr, "\r\n"); + gSkillNames[j] = FStringTable::MakeMacro(textptr, i); + textptr+=i; for (i=0; i sizeof(g_mapInfo[j*MAXLEVELS+k].filename)) - g_mapInfo[j *MAXLEVELS+k].filename = (char *)Xrealloc(g_mapInfo[j*MAXLEVELS+k].filename,(Bstrlen(tempbuf)+1)); - - Bstrcpy(g_mapInfo[j*MAXLEVELS+k].filename,tempbuf); + mapList[j *MAXLEVELS+k].SetFileName(tempbuf); C_SkipComments(); - g_mapInfo[j *MAXLEVELS+k].partime = - (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*REALGAMETICSPERSEC*60)+ - (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))*REALGAMETICSPERSEC); + mapList[j *MAXLEVELS+k].parTime = + (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*60)+ + (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))); textptr += 5; C_SkipSpace(); @@ -2010,9 +1885,9 @@ static int32_t C_ParseCommand(int32_t loop) // cheap hack, 0.99 doesn't have the 3D Realms time if (*(textptr+2) == ':') { - g_mapInfo[j *MAXLEVELS+k].designertime = - (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*REALGAMETICSPERSEC*60)+ - (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))*REALGAMETICSPERSEC); + mapList[j *MAXLEVELS+k].designerTime = + (((*(textptr+0)-'0')*10+(*(textptr+1)-'0'))*60)+ + (((*(textptr+3)-'0')*10+(*(textptr+4)-'0'))); textptr += 5; C_SkipSpace(); @@ -2037,18 +1912,12 @@ static int32_t C_ParseCommand(int32_t loop) tempbuf[i] = '\0'; - if (g_mapInfo[j*MAXLEVELS+k].name == NULL) - g_mapInfo[j*MAXLEVELS+k].name = (char *)Xcalloc(Bstrlen(tempbuf)+1,sizeof(uint8_t)); - else if ((Bstrlen(tempbuf)+1) > sizeof(g_mapInfo[j*MAXLEVELS+k].name)) - g_mapInfo[j *MAXLEVELS+k].name = (char *)Xrealloc(g_mapInfo[j*MAXLEVELS+k].name,(Bstrlen(tempbuf)+1)); - - /* initprintf("level name string len: %d\n",Bstrlen(tempbuf)); */ - - Bstrcpy(g_mapInfo[j*MAXLEVELS+k].name,tempbuf); + mapList[j *MAXLEVELS+k].name = tempbuf; continue; case CON_DEFINEQUOTE: + { g_scriptPtr--; C_GetNextValue(LABEL_DEFINE); @@ -2071,33 +1940,16 @@ static int32_t C_ParseCommand(int32_t loop) C_SkipSpace(); - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - /* - if (*textptr == '%' && *(textptr+1) == 's') - { - initprintf("%s:%d: error: quote text contains string identifier.\n",g_szScriptFileName,g_lineNumber); - g_numCompilerErrors++; - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) textptr++; - break; - } - */ - *(apStrings[k]+i) = *textptr; - - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= MAXQUOTELEN-1)) - { - initprintf("%s:%d: warning: truncating quote text to %d characters.\n",g_scriptFileName,g_lineNumber,MAXQUOTELEN-1); - g_warningCnt++; - C_NextLine(); - break; - } - } - - if ((unsigned)k < MAXQUOTES) - *(apStrings[k]+i) = '\0'; - continue; - + TArray buffer; + while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) + { + buffer.Push(*textptr); + textptr++; + } + buffer.Push(0); + quoteMgr.InitializeQuote(k, buffer.Data(), true); + continue; + } case CON_DEFINESOUND: g_scriptPtr--; C_GetNextValue(LABEL_DEFINE); @@ -2334,14 +2186,6 @@ void C_PrintStats(void) int i, j; - for (i=MAXQUOTES-1, j=0; i>=0; i--) - { - if (apStrings[i]) - j++; - } - - if (j) initprintf("%d strings, ", j); - for (i=MAXTILES-1, j=0; i>=0; i--) { if (g_tile[i].execPtr) @@ -2362,7 +2206,7 @@ void C_Compile(const char *fileName) C_InitHashes(); - auto kFile = kopenFileReader(fileName,0); + auto kFile = fileSystem.OpenFileReader(fileName,0); if (!kFile.isOpen()) { diff --git a/source/rr/src/gameexec.cpp b/source/rr/src/gameexec.cpp index 500b78f5b..e6efa911a 100644 --- a/source/rr/src/gameexec.cpp +++ b/source/rr/src/gameexec.cpp @@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gamecvars.h" #include "debugbreak.h" +extern bool rotatesprite_2doverride; BEGIN_RR_NS @@ -1060,14 +1061,14 @@ static int32_t VM_ResetPlayer(int const playerNum, int32_t vmFlags) //AddLog("resetplayer"); if (!g_netServer && ud.multimode < 2) { +#if 0 if (g_quickload && g_quickload->isValid() && ud.recstat != 2) { - Menu_Open(playerNum); - inputState.ClearKeyStatus(sc_Space); - I_AdvanceTriggerClear(); - Menu_Change(MENU_RESETPLAYER); - } + M_StartControlPanel(false); + M_SetMenu(NAME_ConfirmPlayerReset); + } else +#endif g_player[playerNum].ps->gm = MODE_RESTART; vmFlags |= VM_NOEXECUTE; } @@ -1120,7 +1121,9 @@ void Screen_Play(void) I_ClearAllInput(); - do + auto r2dover = rotatesprite_2doverride; + rotatesprite_2doverride = false; + do { G_HandleAsync(); @@ -1136,6 +1139,7 @@ void Screen_Play(void) videoNextPage(); I_ClearAllInput(); } while (running); + rotatesprite_2doverride = r2dover; } GAMEEXEC_STATIC void VM_Execute(native_t loop) @@ -2453,7 +2457,7 @@ GAMEEXEC_STATIC void VM_Execute(native_t loop) case CON_QUOTE: insptr++; - if (EDUKE32_PREDICT_FALSE((unsigned)(*insptr) >= MAXQUOTES) || apStrings[*insptr] == NULL) + if (EDUKE32_PREDICT_FALSE((unsigned)(*insptr) >= MAXQUOTES)) { CON_ERRPRINTF("invalid quote %d\n", (int32_t)(*insptr)); insptr++; diff --git a/source/rr/src/global.cpp b/source/rr/src/global.cpp index e5a09cf09..09922db2b 100644 --- a/source/rr/src/global.cpp +++ b/source/rr/src/global.cpp @@ -31,13 +31,9 @@ user_defs ud; const char *s_buildDate = "20120522"; -char g_volumeNames[MAXVOLUMES][33] = { "L.A. Meltdown", "Lunar Apocalypse", "Shrapnel City" }; -char g_skillNames[MAXSKILLS][33] = { "Piece Of Cake", "Let's Rock", "Come Get Some", "Damn I'm Good" }; char g_gametypeNames[MAXGAMETYPES][33] = { "DukeMatch (Spawn)", "Cooperative Play", "DukeMatch (No Spawn)", "Team DM (Spawn)", "Team DM (No Spawn)" }; -int32_t g_volumeFlags[MAXVOLUMES]; - int32_t g_gametypeFlags[MAXGAMETYPES] = { GAMETYPE_FRAGBAR | diff --git a/source/rr/src/global.h b/source/rr/src/global.h index dfa1a66a7..28c900642 100644 --- a/source/rr/src/global.h +++ b/source/rr/src/global.h @@ -47,7 +47,6 @@ BEGIN_RR_NS #define MAXINTERPOLATIONS MAXSPRITES // KEEPINSYNC lunatic/con_lang.lua -#define MAXSKILLS 7 // duke3d global soup :( @@ -73,9 +72,7 @@ G_EXTERN actor_t actor[MAXSPRITES]; // g_tile: tile-specific data THAT DOES NOT CHANGE during the course of a game G_EXTERN tiledata_t g_tile[MAXTILES]; G_EXTERN animwalltype animwall[MAXANIMWALLS]; -G_EXTERN char *apStrings[MAXQUOTES],*apXStrings[MAXQUOTES]; G_EXTERN char *label; -G_EXTERN int32_t g_musicIndex; G_EXTERN char g_loadFromGroupOnly; G_EXTERN char g_skillCnt; G_EXTERN char pus,pub; @@ -246,7 +243,6 @@ G_EXTERN playerspawn_t g_playerSpawnPoints[MAXPLAYERS]; G_EXTERN input_t inputfifo[MOVEFIFOSIZ][MAXPLAYERS]; #pragma pack(pop) -G_EXTERN uint8_t g_soundlocks[MAXSOUNDS]; G_EXTERN int32_t g_noEnemies; G_EXTERN int32_t g_restorePalette; G_EXTERN int32_t g_screenCapture; @@ -261,8 +257,6 @@ extern float g_gameUpdateAvgTime; #ifndef global_c_ extern char CheatKeys[2]; extern char g_gametypeNames[MAXGAMETYPES][33]; -extern char g_skillNames[MAXSKILLS][33]; -extern char g_volumeNames[MAXVOLUMES][33]; extern int32_t g_actorRespawnTime; extern int32_t g_bouncemineRadius; @@ -284,7 +278,6 @@ extern int32_t g_volumeCnt; extern int16_t g_blimpSpawnItems[15]; extern int32_t g_gametypeFlags[MAXGAMETYPES]; -extern int32_t g_volumeFlags[MAXVOLUMES]; extern const char *s_buildDate; #endif @@ -292,7 +285,6 @@ extern const char *s_buildDate; enum { EF_HIDEFROMSP = 1<<0, - // EF_HIDEFROMMP = 1<<1, }; EXTERN_INLINE_HEADER void G_UpdateInterpolations(void); diff --git a/source/rr/src/menus.cpp b/source/rr/src/menus.cpp index ad42eb674..06cd11de8 100644 --- a/source/rr/src/menus.cpp +++ b/source/rr/src/menus.cpp @@ -30,2958 +30,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "menus.h" #include "cheats.h" #include "gamecvars.h" +#include "menu/menu.h" +#include "version.h" #include "../../glbackend/glbackend.h" BEGIN_RR_NS -// common positions -#define MENU_MARGIN_REGULAR 40 -#define MENU_MARGIN_WIDE 32 -#define MENU_MARGIN_CENTER 160 -#define MENU_HEIGHT_CENTER 100 - -int32_t g_skillSoundVoice = -1; - -#define USERMAPENTRYLENGTH 25 - -static FORCE_INLINE void Menu_StartTextInput() -{ - inputState.keyFlushChars(); - inputState.ClearKeysDown(); -} - -static FORCE_INLINE void Menu_StopTextInput() -{ -} - -static FORCE_INLINE void rotatesprite_ybounds(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, int32_t ydim_upper, int32_t ydim_lower) -{ - rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, 0, ydim_upper, xdim-1, ydim_lower); -} - -static void mgametext(int32_t x, int32_t y, char const * t) -{ - G_ScreenText(MF_Bluefont.tilenum, x, y, MF_Bluefont.zoom, 0, 0, t, 0, MF_Bluefont.pal, 2|8|16|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags, 0, 0, xdim-1, ydim-1); -} - -static vec2_t mgametextcenter(int32_t x, int32_t y, char const * t, int32_t f = 0) -{ - return G_ScreenText(MF_Bluefont.tilenum, (MENU_MARGIN_CENTER<<16) + x, y, MF_Bluefont.zoom, 0, 0, t, 0, MF_Bluefont.pal, 2|8|16|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags|f|TEXT_XCENTER, 0, 0, xdim-1, ydim-1); -} - -#define mminitext(x,y,t,p) minitext_(x, y, t, 0, p, 2|8|16|ROTATESPRITE_FULL16) -#define mmenutext menutext - -static void shadowminitext(int32_t x, int32_t y, const char *t, int32_t p) -{ - int32_t f = 0; - - if (!minitext_lowercase) - f |= TEXT_UPPERCASE; - - G_ScreenTextShadow(1, 1, MINIFONT, x, y, RR ? 32768 : 65536, 0, 0, t, 0, p, 2|8|16|ROTATESPRITE_FULL16, 0, 4<<16, 8<<16, 1<<16, 0, f, 0, 0, xdim-1, ydim-1); -} - -static void creditsminitext(int32_t x, int32_t y, const char *t, int32_t p) -{ - int32_t f = TEXT_XCENTER; - - if (!minitext_lowercase) - f |= TEXT_UPPERCASE; - - G_ScreenTextShadow(1, 1, MINIFONT, x, y, RR ? 32768 : 65536, 0, 0, t, 0, p, 2|8|16|ROTATESPRITE_FULL16, 0, 4<<16, 8<<16, 1<<16, 0, f, 0, 0, xdim-1, ydim-1); -} - -#pragma pack(push,1) -static savehead_t savehead; -#pragma pack(pop) - -static void Menu_DrawBackground(const vec2_t origin) -{ - rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (100<<16), 65536L,0,MENUSCREEN,16,0,10+64); -} - -static void Menu_DrawTopBar(const vec2_t origin) -{ - rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (19<<16), MF_Redfont.cursorScale3, 0,MENUBAR,16,0,10); -} - -static void Menu_DrawTopBarCaption(const char *caption, const vec2_t origin) -{ - static char t[64]; - size_t const srclen = strlen(caption); - size_t const dstlen = min(srclen, ARRAY_SIZE(t)-1); - memcpy(t, caption, dstlen); - t[dstlen] = '\0'; - char *p = &t[dstlen-1]; - if (*p == ':') - *p = '\0'; - captionmenutext(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (24<<16) + (15<<15), t); -} - -static FORCE_INLINE int32_t Menu_CursorShade(void) -{ - return 4-(sintable[((int32_t) totalclock<<4)&2047]>>11); -} -static void Menu_DrawCursorCommon(int32_t x, int32_t y, int32_t z, int32_t picnum, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1) -{ - rotatesprite_(x, y, z, 0, picnum, Menu_CursorShade(), 0, 2|8, 0, 0, 0, ydim_upper, xdim-1, ydim_lower); -} -static void Menu_DrawCursorLeft(int32_t x, int32_t y, int32_t z) -{ - const int frames = RR ? 16 : 7; - Menu_DrawCursorCommon(x, y, z, SPINNINGNUKEICON+(((int32_t) totalclock>>3)%frames)); -} -static void Menu_DrawCursorRight(int32_t x, int32_t y, int32_t z) -{ - const int frames = RR ? 16 : 7; - Menu_DrawCursorCommon(x, y, z, SPINNINGNUKEICON+frames-1-((frames-1+((int32_t) totalclock>>3))%frames)); -} -static void Menu_DrawCursorTextTile(int32_t x, int32_t y, int32_t h, int32_t picnum, vec2_16_t const & siz, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1) -{ - vec2_t const adjsiz = { siz.x<<15, siz.y<<16 }; - Menu_DrawCursorCommon(x + scale(adjsiz.x, h, adjsiz.y), y, divscale16(h, adjsiz.y), picnum, ydim_upper, ydim_lower); -} -static void Menu_DrawCursorText(int32_t x, int32_t y, int32_t h, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1) -{ - vec2_16_t const & siz = tilesiz[SPINNINGNUKEICON]; - const int frames = RR ? 16 : 7; - - if (siz.x == 0) - { - Menu_DrawCursorTextTile(x, y, h, SMALLFNTCURSOR, tilesiz[SMALLFNTCURSOR], ydim_upper, ydim_lower); - return; - } - - Menu_DrawCursorTextTile(x, y, h, SPINNINGNUKEICON+(((int32_t) totalclock>>3)%frames), siz, ydim_upper, ydim_lower); -} - - -static uint16_t g_oldSaveCnt; - - - - -/* -All MAKE_* macros are generally for the purpose of keeping state initialization -separate from actual data. Alternatively, they can serve to factor out repetitive -stuff and keep the important bits from getting lost to our eyes. - -They serve as a stand-in for C++ default value constructors, since we're using C89. - -Note that I prefer to include a space on the inside of the macro parentheses, since -they effectively stand in for curly braces as struct initializers. -*/ - - -// common font types -// tilenums are set after namesdyn runs - -// emptychar x,y between x,y zoom cursorLeft cursorCenter cursorScale textflags -// tilenum shade_deselected shade_disabled pal pal_selected pal_deselected pal_disabled -MenuFont_t MF_Redfont = { { 5<<16, 15<<16 }, { 0, 0 }, 65536, 20<<16, 110<<16, 65536, 65536, 65536, TEXT_BIGALPHANUM | TEXT_UPPERCASE, - -1, 10, 0, 0, 0, 0, 1, - 0, 0, 1 }; -MenuFont_t MF_Bluefont = { { 5<<16, 7<<16 }, { 0, 0 }, 65536, 10<<16, 110<<16, 32768, 65536, 65536, 0, - -1, 10, 0, 0, 10, 10, 16, - 0, 0, 16 }; -MenuFont_t MF_Minifont = { { 4<<16, 5<<16 }, { 1<<16, 1<<16 }, 65536, 10<<16, 110<<16, 32768, 65536, 65536, 0, - -1, 10, 0, 0, 2, 2, 0, - 0, 0, 16 }; - - -static MenuMenuFormat_t MMF_Top_Main = { { MENU_MARGIN_CENTER<<16, 55<<16, }, -(170<<16) }; -static MenuMenuFormat_t MMF_Top_Episode = { { MENU_MARGIN_CENTER<<16, 48<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_Top_Skill = { { MENU_MARGIN_CENTER<<16, 58<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_Top_Options = { { MENU_MARGIN_CENTER<<16, 38<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_Top_Joystick_Network = { { MENU_MARGIN_CENTER<<16, 70<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_BigOptions = { { MENU_MARGIN_WIDE<<16, 38<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_SmallOptions = { { MENU_MARGIN_WIDE<<16, 37<<16, }, 170<<16 }; -static MenuMenuFormat_t MMF_Macros = { { 26<<16, 40<<16, }, 160<<16 }; -static MenuMenuFormat_t MMF_SmallOptionsNarrow = { { MENU_MARGIN_REGULAR<<16, 38<<16, }, -(190<<16) }; -static MenuMenuFormat_t MMF_KeyboardSetupFuncs = { { 50<<16, 34<<16, }, 151<<16 }; -static MenuMenuFormat_t MMF_MouseJoySetupBtns = { { 76<<16, 34<<16, }, 143<<16 }; -static MenuMenuFormat_t MMF_FuncList = { { 100<<16, 51<<16, }, 152<<16 }; -static MenuMenuFormat_t MMF_ColorCorrect = { { MENU_MARGIN_REGULAR<<16, 86<<16, }, 190<<16 }; -static MenuMenuFormat_t MMF_BigSliders = { { MENU_MARGIN_WIDE<<16, 37<<16, }, 190<<16 }; -static MenuMenuFormat_t MMF_LoadSave = { { 200<<16, 49<<16, }, 145<<16 }; -static MenuMenuFormat_t MMF_NetSetup = { { 36<<16, 38<<16, }, 190<<16 }; -static MenuMenuFormat_t MMF_FileSelectLeft = { { 40<<16, 45<<16, }, 162<<16 }; -static MenuMenuFormat_t MMF_FileSelectRight = { { 164<<16, 45<<16, }, 162<<16 }; - -static MenuEntryFormat_t MEF_Null = { 0, 0, 0 }; -static MenuEntryFormat_t MEF_MainMenu = { 4<<16, 0, 0 }; -static MenuEntryFormat_t MEF_OptionsMenu = { 7<<16, 0, 0 }; -static MenuEntryFormat_t MEF_CenterMenu = { 7<<16, 0, 0 }; -static MenuEntryFormat_t MEF_BigOptions_Apply = { 4<<16, 16<<16, -(260<<16) }; -static MenuEntryFormat_t MEF_BigOptionsRt = { 4<<16, 0, -(260<<16) }; -#if defined USE_OPENGL || !defined EDUKE32_ANDROID_MENU -static MenuEntryFormat_t MEF_SmallOptions = { 1<<16, 0, -(260<<16) }; -#endif -static MenuEntryFormat_t MEF_BigCheats = { 3<<16, 0, -(260<<16) }; -static MenuEntryFormat_t MEF_Cheats = { 2<<16, 0, -(260<<16) }; -static MenuEntryFormat_t MEF_PlayerNarrow = { 1<<16, 0, 90<<16 }; -static MenuEntryFormat_t MEF_Macros = { 2<<16, -1, 268<<16 }; -static MenuEntryFormat_t MEF_VideoSetup = { 4<<16, 0, 168<<16 }; -static MenuEntryFormat_t MEF_VideoSetup_Apply = { 4<<16, 16<<16, 168<<16 }; -static MenuEntryFormat_t MEF_KBFuncList = { 3<<16, 0, -(225<<16) }; -static MenuEntryFormat_t MEF_FuncList = { 3<<16, 0, -(170<<16) }; -static MenuEntryFormat_t MEF_ColorCorrect = { 2<<16, 0, -(240<<16) }; -static MenuEntryFormat_t MEF_BigSliders = { 2<<16, 0, -(260<<16) }; -static MenuEntryFormat_t MEF_LoadSave = { 2<<16, -1, 78<<16 }; -static MenuEntryFormat_t MEF_NetSetup = { 4<<16, 0, 112<<16 }; -static MenuEntryFormat_t MEF_NetSetup_Confirm = { 4<<16, 16<<16, 112<<16 }; - -// common menu option sets -#define MAKE_MENUOPTIONSET(optionNames, optionValues, features) { optionNames, optionValues, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, ARRAY_SIZE(optionNames), -1, 0, features } -#define MAKE_MENUOPTIONSETDYN(optionNames, optionValues, numOptions, features) { optionNames, optionValues, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, numOptions, -1, 0, features } -#define MAKE_MENUOPTIONSETNULL { NULL, NULL, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, 0, -1, 0, 0 } - -static char const *MEOSN_OffOn[] = { "Off", "On", }; -static MenuOptionSet_t MEOS_OffOn = MAKE_MENUOPTIONSET( MEOSN_OffOn, NULL, 0x3 ); -static char const *MEOSN_OnOff[] = { "On", "Off", }; -static MenuOptionSet_t MEOS_OnOff = MAKE_MENUOPTIONSET( MEOSN_OnOff, NULL, 0x3 ); -static char const *MEOSN_NoYes[] = { "No", "Yes", }; -static MenuOptionSet_t MEOS_NoYes = MAKE_MENUOPTIONSET( MEOSN_NoYes, NULL, 0x3 ); -static char const *MEOSN_YesNo[] = { "Yes", "No", }; -static MenuOptionSet_t MEOS_YesNo = MAKE_MENUOPTIONSET( MEOSN_YesNo, NULL, 0x3 ); - - -static FString MenuGameFuncs[NUMGAMEFUNCTIONS]; -static char const *MenuGameFuncNone = " -None-"; -static char const *MEOSN_Gamefuncs[NUMGAMEFUNCTIONS+1]; -static int32_t MEOSV_Gamefuncs[NUMGAMEFUNCTIONS+1]; -static MenuOptionSet_t MEOS_Gamefuncs = MAKE_MENUOPTIONSET( MEOSN_Gamefuncs, MEOSV_Gamefuncs, 0x1 ); - - - -/* -MenuEntry_t is passed in arrays of pointers so that the callback function -that is called when an entry is modified or activated can test equality of the current -entry pointer directly against the known ones, instead of relying on an ID number. - -That way, individual menu entries can be ifdef'd out painlessly. -*/ - -static MenuLink_t MEO_NULL = { MENU_NULL, MA_None, }; -static const char* MenuCustom = "Custom"; - -#define MAKE_MENUSTRING(...) { NULL, __VA_ARGS__, } -#define MAKE_MENUOPTION(...) { __VA_ARGS__, -1, } -#define MAKE_MENURANGE(...) { __VA_ARGS__, } -#define MAKE_MENUENTRY(...) { __VA_ARGS__, 0, 0, 0, } - - -#define MAKE_SPACER( EntryName, Height ) \ -static MenuSpacer_t MEO_ ## EntryName = { Height }; - -MAKE_SPACER( Space2, 2<<16 ); // bigoptions -MAKE_SPACER( Space4, 4<<16 ); // usermap, smalloptions, anything else non-top -MAKE_SPACER( Space6, 6<<16 ); // videosetup -MAKE_SPACER( Space8, 8<<16 ); // colcorr, redslide - -static MenuEntry_t ME_Space2_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space2, Spacer ); -static MenuEntry_t ME_Space4_Bluefont = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Null, &MEO_Space4, Spacer ); -#ifndef EDUKE32_SIMPLE_MENU -static MenuEntry_t ME_Space4_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space4, Spacer ); -static MenuEntry_t ME_Space8_Bluefont = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Null, &MEO_Space8, Spacer ); -#endif -static MenuEntry_t ME_Space6_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space6, Spacer ); -static MenuEntry_t ME_Space8_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space8, Spacer ); - -#define MAKE_MENU_TOP_ENTRYLINK( Title, Format, EntryName, LinkID ) \ -static MenuLink_t MEO_ ## EntryName = { LinkID, MA_Advance, };\ -static MenuEntry_t ME_ ## EntryName = MAKE_MENUENTRY( Title, &MF_Redfont, &Format, &MEO_ ## EntryName, Link ) - -static char const s_NewGame[] = "New Game"; -static char const s_SaveGame[] = "Save Game"; -static char const s_LoadGame[] = "Load Game"; -static char const s_Continue[] = "Continue"; -static char const s_Options[] = "Options"; -static char const s_Credits[] = "Credits"; - -MAKE_MENU_TOP_ENTRYLINK( s_NewGame, MEF_MainMenu, MAIN_NEWGAME, MENU_EPISODE ); -#ifdef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK( "Resume Game", MEF_MainMenu, MAIN_RESUMEGAME, MENU_CLOSE ); -#endif -MAKE_MENU_TOP_ENTRYLINK( s_NewGame, MEF_MainMenu, MAIN_NEWGAME_INGAME, MENU_NEWVERIFY ); -static MenuLink_t MEO_MAIN_NEWGAME_NETWORK = { MENU_NETWORK, MA_Advance, }; -MAKE_MENU_TOP_ENTRYLINK( s_SaveGame, MEF_MainMenu, MAIN_SAVEGAME, MENU_SAVE ); -MAKE_MENU_TOP_ENTRYLINK( s_LoadGame, MEF_MainMenu, MAIN_LOADGAME, MENU_LOAD ); -MAKE_MENU_TOP_ENTRYLINK( s_Options, MEF_MainMenu, MAIN_OPTIONS, MENU_OPTIONS ); -MAKE_MENU_TOP_ENTRYLINK("Help", MEF_MainMenu, MAIN_HELP, MENU_STORY); -#ifndef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK( s_Credits, MEF_MainMenu, MAIN_CREDITS, MENU_CREDITS ); -#endif -MAKE_MENU_TOP_ENTRYLINK( "End Game", MEF_MainMenu, MAIN_QUITTOTITLE, MENU_QUITTOTITLE ); -MAKE_MENU_TOP_ENTRYLINK( "Quit", MEF_MainMenu, MAIN_QUIT, MENU_QUIT ); -#ifndef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK( "Quit Game", MEF_MainMenu, MAIN_QUITGAME, MENU_QUIT ); -#endif - -static MenuEntry_t *MEL_MAIN[] = { - &ME_MAIN_NEWGAME, - &ME_MAIN_LOADGAME, - &ME_MAIN_OPTIONS, - &ME_MAIN_HELP, -#ifndef EDUKE32_SIMPLE_MENU - &ME_MAIN_CREDITS, -#endif - &ME_MAIN_QUIT, -}; - -static MenuEntry_t *MEL_MAIN_INGAME[] = { -#ifdef EDUKE32_SIMPLE_MENU - &ME_MAIN_RESUMEGAME, -#else - &ME_MAIN_NEWGAME_INGAME, -#endif - &ME_MAIN_SAVEGAME, - &ME_MAIN_LOADGAME, - &ME_MAIN_OPTIONS, - &ME_MAIN_HELP, - &ME_MAIN_QUITTOTITLE, -#ifndef EDUKE32_SIMPLE_MENU - &ME_MAIN_QUITGAME, -#endif -}; - -// Episode and Skill will be dynamically generated after CONs are parsed -static MenuLink_t MEO_EPISODE = { MENU_SKILL, MA_Advance, }; -static MenuLink_t MEO_EPISODE_SHAREWARE = { MENU_BUYDUKE, MA_Advance, }; -static MenuEntry_t ME_EPISODE_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_CenterMenu, &MEO_EPISODE, Link ); -static MenuEntry_t ME_EPISODE[MAXVOLUMES]; -static MenuLink_t MEO_EPISODE_USERMAP = { MENU_USERMAP, MA_Advance, }; -static MenuEntry_t ME_EPISODE_USERMAP = MAKE_MENUENTRY( "User Map", &MF_Redfont, &MEF_CenterMenu, &MEO_EPISODE_USERMAP, Link ); -static MenuEntry_t *MEL_EPISODE[MAXVOLUMES+2]; // +2 for spacer and User Map - -static MenuEntry_t ME_SKILL_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_CenterMenu, &MEO_NULL, Link ); -static MenuEntry_t ME_SKILL[MAXSKILLS]; -static MenuEntry_t *MEL_SKILL[MAXSKILLS]; - -static char const *MEOSN_GAMESETUP_AIM_AUTO[] = { "Never", "Always", "Hitscan only", -}; -static int32_t MEOSV_GAMESETUP_AIM_AUTO[] = { 0, 1, 2, -}; - -static MenuOptionSet_t MEOS_GAMESETUP_AIM_AUTO = MAKE_MENUOPTIONSET( MEOSN_GAMESETUP_AIM_AUTO, MEOSV_GAMESETUP_AIM_AUTO, 0x2 ); -static MenuOption_t MEO_GAMESETUP_AIM_AUTO = MAKE_MENUOPTION( &MF_Redfont, &MEOS_GAMESETUP_AIM_AUTO, &cl_autoaim ); -static MenuEntry_t ME_GAMESETUP_AIM_AUTO = MAKE_MENUENTRY( "Auto aim:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_AIM_AUTO, Option ); - -static char const *MEOSN_GAMESETUP_WEAPSWITCH_PICKUP[] = { "Never", "If new", "By rating", }; -static MenuOptionSet_t MEOS_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUOPTIONSET( MEOSN_GAMESETUP_WEAPSWITCH_PICKUP, NULL, 0x2 ); -static MenuOption_t MEO_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUOPTION( &MF_Redfont, &MEOS_GAMESETUP_WEAPSWITCH_PICKUP, NULL ); -static MenuEntry_t ME_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUENTRY( "Equip pickups:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_WEAPSWITCH_PICKUP, Option ); - -static char const *MEOSN_DemoRec[] = { "Off", "Running", }; -static MenuOptionSet_t MEOS_DemoRec = MAKE_MENUOPTIONSET( MEOSN_DemoRec, NULL, 0x3 ); -static MenuOption_t MEO_GAMESETUP_DEMOREC = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &m_recstat ); -static MenuEntry_t ME_GAMESETUP_DEMOREC = MAKE_MENUENTRY( "Record demo:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_DEMOREC, Option ); - -static MenuOption_t MEO_ADULTMODE = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &adult_lockout); -static MenuEntry_t ME_ADULTMODE = MAKE_MENUENTRY( "Parental lock:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_ADULTMODE, Option ); - -#if defined(EDUKE32_ANDROID_MENU) || !defined(EDUKE32_SIMPLE_MENU) -static MenuLink_t MEO_GAMESETUP_CHEATS = { MENU_CHEATS, MA_Advance, }; -static MenuEntry_t ME_GAMESETUP_CHEATS = MAKE_MENUENTRY( "Cheats", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_CHEATS, Link ); - -static MenuEntry_t *MEL_GAMESETUP[] = { - &ME_ADULTMODE, -#if defined STARTUP_SETUP_WINDOW && !defined EDUKE32_SIMPLE_MENU - &ME_GAMESETUP_STARTWIN, -#endif - &ME_GAMESETUP_AIM_AUTO, - //&ME_GAMESETUP_WEAPSWITCH_PICKUP, -#ifdef EDUKE32_ANDROID_MENU - &ME_GAMESETUP_QUICKSWITCH, - &ME_GAMESETUP_CROUCHLOCK, -#else - &ME_GAMESETUP_DEMOREC, -#endif - &ME_GAMESETUP_CHEATS, -}; -#endif - -#ifndef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK( "Game Setup", MEF_OptionsMenu, OPTIONS_GAMESETUP, MENU_GAMESETUP ); -#endif -MAKE_MENU_TOP_ENTRYLINK( "Sound Setup", MEF_OptionsMenu, OPTIONS_SOUNDSETUP, MENU_SOUND ); -MAKE_MENU_TOP_ENTRYLINK( "Display Setup", MEF_OptionsMenu, OPTIONS_DISPLAYSETUP, MENU_DISPLAYSETUP ); -MAKE_MENU_TOP_ENTRYLINK( "Player Setup", MEF_OptionsMenu, OPTIONS_PLAYERSETUP, MENU_PLAYER ); -#ifndef EDUKE32_ANDROID_MENU -MAKE_MENU_TOP_ENTRYLINK( "Control Setup", MEF_OptionsMenu, OPTIONS_CONTROLS, MENU_CONTROLS ); - -MAKE_MENU_TOP_ENTRYLINK( "Configure Controls", MEF_CenterMenu, OPTIONS_KEYBOARDSETUP, MENU_KEYBOARDSETUP ); -MAKE_MENU_TOP_ENTRYLINK( "Mouse Setup", MEF_CenterMenu, OPTIONS_MOUSESETUP, MENU_MOUSESETUP ); -#endif -MAKE_MENU_TOP_ENTRYLINK( "Joystick Setup", MEF_CenterMenu, OPTIONS_JOYSTICKSETUP, MENU_JOYSTICKSETUP ); -#ifdef EDUKE32_ANDROID_MENU -MAKE_MENU_TOP_ENTRYLINK( "Touch Setup", MEF_CenterMenu, OPTIONS_TOUCHSETUP, MENU_TOUCHSETUP ); -#endif -#ifdef EDUKE32_SIMPLE_MENU -MAKE_MENU_TOP_ENTRYLINK("Cheats", MEF_OptionsMenu, OPTIONS_CHEATS, MENU_CHEATS); -#endif - -// Zhe menu code lacks flexibility, it can either be hardwired to ints or to CVARs. -// Since CVARs are more important it means that these need to be implemented as CVARs even though they are just temporaries. -// By giving them no name we ensure that they remain outside the CVAR system. -CVAR_UNAMED(Int, newresolution) -CVAR_UNAMED(Int, newrendermode) -CVAR_UNAMED(Int, newfullscreen) -CVAR_UNAMED(Int, newvsync) -CVAR_UNAMED(Int, newborderless) - -enum resflags_t { - RES_FS = 0x1, - RES_WIN = 0x2, -}; - -#define MAXRESOLUTIONSTRINGLENGTH 19 - -typedef struct resolution_t { - int32_t xdim, ydim; - int32_t flags; - int32_t bppmax; - char name[MAXRESOLUTIONSTRINGLENGTH]; -} resolution_t; - -resolution_t resolution[MAXVALIDMODES]; - -static char const *MEOSN_VIDEOSETUP_RESOLUTION[MAXVALIDMODES]; -static MenuOptionSet_t MEOS_VIDEOSETUP_RESOLUTION = MAKE_MENUOPTIONSETDYN( MEOSN_VIDEOSETUP_RESOLUTION, NULL, 0, 0x0 ); -static MenuOption_t MEO_VIDEOSETUP_RESOLUTION = MAKE_MENUOPTION( &MF_Redfont, &MEOS_VIDEOSETUP_RESOLUTION, &newresolution ); -static MenuEntry_t ME_VIDEOSETUP_RESOLUTION = MAKE_MENUENTRY( "Resolution:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_RESOLUTION, Option ); - -#ifdef USE_OPENGL -static char const *MEOSN_VIDEOSETUP_RENDERER[] = { "Classic", "OpenGL", }; -static int32_t MEOSV_VIDEOSETUP_RENDERER[] = { REND_CLASSIC, REND_POLYMOST, }; - -static MenuOptionSet_t MEOS_VIDEOSETUP_RENDERER = MAKE_MENUOPTIONSET( MEOSN_VIDEOSETUP_RENDERER, MEOSV_VIDEOSETUP_RENDERER, 0x2 ); - -static MenuOption_t MEO_VIDEOSETUP_RENDERER = MAKE_MENUOPTION( &MF_Redfont, &MEOS_VIDEOSETUP_RENDERER, &newrendermode ); -static MenuEntry_t ME_VIDEOSETUP_RENDERER = MAKE_MENUENTRY( "Renderer:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_RENDERER, Option ); -#endif - -static MenuOption_t MEO_VIDEOSETUP_FULLSCREEN = MAKE_MENUOPTION( &MF_Redfont, &MEOS_YesNo, &newfullscreen ); -static MenuEntry_t ME_VIDEOSETUP_FULLSCREEN = MAKE_MENUENTRY( "Windowed:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_FULLSCREEN, Option ); - - -static char const *MEOSN_VIDEOSETUP_VSYNC [] = { "Adaptive", "Off", "On", }; -static int32_t MEOSV_VIDEOSETUP_VSYNC [] = { -1, 0, 1, }; -static MenuOptionSet_t MEOS_VIDEOSETUP_VSYNC = MAKE_MENUOPTIONSET(MEOSN_VIDEOSETUP_VSYNC, MEOSV_VIDEOSETUP_VSYNC, 0x2); -static MenuOption_t MEO_VIDEOSETUP_VSYNC = MAKE_MENUOPTION(&MF_Redfont, &MEOS_VIDEOSETUP_VSYNC, &newvsync); -static MenuEntry_t ME_VIDEOSETUP_VSYNC = MAKE_MENUENTRY("VSync:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_VSYNC, Option); - -//static char const *MEOSN_VIDEOSETUP_FRAMELIMIT [] = { "30 fps", "60 fps", "75 fps", "100 fps", "120 fps", "144 fps", "165 fps", "240 fps" }; - -static MenuEntry_t ME_VIDEOSETUP_APPLY = MAKE_MENUENTRY( "Apply Changes", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_NULL, Link ); - - -static MenuLink_t MEO_DISPLAYSETUP_COLORCORR = { MENU_COLCORR, MA_Advance, }; -static MenuEntry_t ME_DISPLAYSETUP_COLORCORR = MAKE_MENUENTRY( "Color Correction", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_COLORCORR, Link ); - - -#ifndef EDUKE32_ANDROID_MENU -static MenuOption_t MEO_DISPLAYSETUP_ASPECTRATIO = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &r_usenewaspect); -static MenuEntry_t ME_DISPLAYSETUP_ASPECTRATIO = MAKE_MENUENTRY( "Widescreen:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ASPECTRATIO, Option ); -#endif - -static MenuOption_t MEO_DISPLAYSETUP_VOXELS = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &r_voxels); -static MenuEntry_t ME_DISPLAYSETUP_VOXELS = MAKE_MENUENTRY( "Voxels:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_VOXELS, Option ); - -static MenuRangeInt32_t MEO_DISPLAYSETUP_FOV = MAKE_MENURANGE( &r_fov, &MF_Redfont, 70, 120, 0, 11, 1 ); -static MenuEntry_t ME_DISPLAYSETUP_FOV = MAKE_MENUENTRY( "FOV:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_FOV, RangeInt32 ); - - -#ifdef USE_OPENGL - -//POGOTODO: allow filtering again in standalone once indexed colour textures support filtering -static char const *MEOSN_DISPLAYSETUP_TEXFILTER[] = { "Classic", "Filtered" }; -static int32_t MEOSV_DISPLAYSETUP_TEXFILTER[] = { TEXFILTER_OFF, TEXFILTER_ON }; -static MenuOptionSet_t MEOS_DISPLAYSETUP_TEXFILTER = MAKE_MENUOPTIONSET( MEOSN_DISPLAYSETUP_TEXFILTER, MEOSV_DISPLAYSETUP_TEXFILTER, 0x2 ); -static MenuOption_t MEO_DISPLAYSETUP_TEXFILTER = MAKE_MENUOPTION( &MF_Redfont, &MEOS_DISPLAYSETUP_TEXFILTER, &hw_texfilter ); -static MenuEntry_t ME_DISPLAYSETUP_TEXFILTER = MAKE_MENUENTRY( "Texture Mode:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_TEXFILTER, Option ); - -static char const *MEOSN_DISPLAYSETUP_ANISOTROPY[] = { "Max", "None", "2x", "4x", "8x", "16x", }; -static int32_t MEOSV_DISPLAYSETUP_ANISOTROPY[] = { 0, 1, 2, 4, 8, 16, }; -static MenuOptionSet_t MEOS_DISPLAYSETUP_ANISOTROPY = MAKE_MENUOPTIONSET( MEOSN_DISPLAYSETUP_ANISOTROPY, MEOSV_DISPLAYSETUP_ANISOTROPY, 0x0 ); -static MenuOption_t MEO_DISPLAYSETUP_ANISOTROPY = MAKE_MENUOPTION(&MF_Redfont, &MEOS_DISPLAYSETUP_ANISOTROPY, &hw_anisotropy); -static MenuEntry_t ME_DISPLAYSETUP_ANISOTROPY = MAKE_MENUENTRY( "Anisotropy:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ANISOTROPY, Option ); - -#endif - -static char const s_Scale[] = "Scale:"; - -static MenuOption_t MEO_SCREENSETUP_CROSSHAIR = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &cl_crosshair); -static MenuEntry_t ME_SCREENSETUP_CROSSHAIR = MAKE_MENUENTRY( "Crosshair:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_CROSSHAIR, Option ); -static MenuRangeInt32_t MEO_SCREENSETUP_CROSSHAIRSIZE = MAKE_MENURANGE( &cl_crosshairscale, &MF_Redfont, 25, 100, 0, 16, 2 ); -static MenuEntry_t ME_SCREENSETUP_CROSSHAIRSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_CROSSHAIRSIZE, RangeInt32 ); - -static MenuRangeInt32_t MEO_SCREENSETUP_SCREENSIZE = MAKE_MENURANGE( &hud_size, &MF_Redfont, 0, 11, 0, 1, EnforceIntervals ); -static MenuOption_t MEO_SCREENSETUP_SCREENSIZE_TWO = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &hud_size ); -static MenuEntry_t ME_SCREENSETUP_SCREENSIZE = MAKE_MENUENTRY( "Status bar:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_SCREENSIZE, RangeInt32 ); -static MenuRangeInt32_t MEO_SCREENSETUP_TEXTSIZE = MAKE_MENURANGE( &hud_textscale, &MF_Redfont, 100, 400, 0, 16, 2 ); -static MenuEntry_t ME_SCREENSETUP_TEXTSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_TEXTSIZE, RangeInt32 ); -static MenuOption_t MEO_SCREENSETUP_LEVELSTATS = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &hud_stats); -static MenuEntry_t ME_SCREENSETUP_LEVELSTATS = MAKE_MENUENTRY( "Level stats:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_LEVELSTATS, Option ); - - -static MenuOption_t MEO_SCREENSETUP_SHOWPICKUPMESSAGES = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &hud_messages); -static MenuEntry_t ME_SCREENSETUP_SHOWPICKUPMESSAGES = MAKE_MENUENTRY( "Game messages:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_SHOWPICKUPMESSAGES, Option ); - -static MenuRangeInt32_t MEO_SCREENSETUP_SBARSIZE = MAKE_MENURANGE( &hud_scale, &MF_Redfont, 50, 100, 0, 10, 2 ); -static MenuEntry_t ME_SCREENSETUP_SBARSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_SBARSIZE, RangeInt32 ); - - -static MenuLink_t MEO_DISPLAYSETUP_SCREENSETUP = { MENU_SCREENSETUP, MA_Advance, }; -static MenuEntry_t ME_DISPLAYSETUP_SCREENSETUP = MAKE_MENUENTRY( "HUD setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_SCREENSETUP, Link ); - - -#ifdef USE_OPENGL -static MenuLink_t MEO_DISPLAYSETUP_ADVANCED_GL_POLYMOST = { MENU_POLYMOST, MA_Advance, }; -static MenuEntry_t ME_DISPLAYSETUP_ADVANCED_GL_POLYMOST = MAKE_MENUENTRY( "Polymost setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ADVANCED_GL_POLYMOST, Link ); -#endif - -#ifndef EDUKE32_ANDROID_MENU -static MenuLink_t MEO_DISPLAYSETUP_VIDEOSETUP = { MENU_VIDEOSETUP, MA_Advance, }; -static MenuEntry_t ME_DISPLAYSETUP_VIDEOSETUP = MAKE_MENUENTRY( "Video mode", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_VIDEOSETUP, Link ); -#endif - - -static MenuLink_t MEO_ENTERCHEAT = { MENU_CHEATENTRY, MA_None, }; -static MenuEntry_t ME_ENTERCHEAT = MAKE_MENUENTRY( "Enter Cheat Code", &MF_Redfont, &MEF_BigCheats, &MEO_ENTERCHEAT, Link ); - -static MenuLink_t MEO_CHEAT_WARP = { MENU_CHEAT_WARP, MA_None, }; -static MenuLink_t MEO_CHEAT_SKILL = { MENU_CHEAT_SKILL, MA_None, }; -// KEEPINSYNC game.h: enum CheatCodeFunctions -// KEEPINSYNC game.c: uint8_t CheatFunctionIDs[] -#define MAKE_MENUCHEAT( Name ) MAKE_MENUENTRY( Name, &MF_Bluefont, &MEF_Cheats, &MEO_NULL, Link ) -static MenuEntry_t ME_CheatCodes[] = { - MAKE_MENUCHEAT( "Toggle Cashman" ), - MAKE_MENUCHEAT( "Toggle God Mode" ), - MAKE_MENUCHEAT( "Give Everything" ), - MAKE_MENUCHEAT( "Give Weapons" ), - MAKE_MENUCHEAT( "Give All Items" ), - MAKE_MENUCHEAT( "Give Inventory" ), - MAKE_MENUCHEAT( "Give Keys" ), - MAKE_MENUCHEAT( "Toggle Hyper" ), - MAKE_MENUCHEAT( "Toggle 3rd-Person View" ), - MAKE_MENUCHEAT( "Toggle Show All Map" ), - MAKE_MENUCHEAT( "Toggle All Locks" ), - MAKE_MENUCHEAT( "Toggle Clipping" ), - MAKE_MENUENTRY( "Level Warp", &MF_Bluefont, &MEF_Cheats, &MEO_CHEAT_WARP, Link ), - MAKE_MENUENTRY( "Change Skill", &MF_Bluefont, &MEF_Cheats, &MEO_CHEAT_SKILL, Link ), - MAKE_MENUCHEAT( "Toggle Monsters" ), - MAKE_MENUCHEAT( "Toggle Framerate Display" ), - MAKE_MENUCHEAT( NULL ), - MAKE_MENUCHEAT( NULL ), - MAKE_MENUCHEAT( NULL ), - MAKE_MENUCHEAT( "Toggle Coordinate Display" ), - MAKE_MENUCHEAT( "Toggle Debug Data Dump" ), -}; - -static MenuEntry_t *MEL_OPTIONS[] = { -#ifndef EDUKE32_SIMPLE_MENU - &ME_OPTIONS_GAMESETUP, -#endif - &ME_OPTIONS_DISPLAYSETUP, - &ME_OPTIONS_SOUNDSETUP, -#ifndef EDUKE32_ANDROID_MENU -#ifndef EDUKE32_SIMPLE_MENU - &ME_OPTIONS_PLAYERSETUP, -#endif - &ME_OPTIONS_CONTROLS, -#else - &ME_OPTIONS_TOUCHSETUP, -#endif -#ifdef EDUKE32_SIMPLE_MENU - &ME_GAMESETUP_SAVESETUP, - &ME_OPTIONS_CHEATS -#endif -}; - -static MenuEntry_t *MEL_CONTROLS[] = { -#ifndef EDUKE32_ANDROID_MENU - &ME_OPTIONS_KEYBOARDSETUP, - &ME_OPTIONS_MOUSESETUP, - &ME_OPTIONS_JOYSTICKSETUP, -#else - &ME_OPTIONS_TOUCHSETUP -#endif -}; - -static MenuEntry_t *MEL_CHEATS[ARRAY_SIZE(ME_CheatCodes)+1] = { - &ME_ENTERCHEAT, -}; - -static MenuEntry_t *MEL_VIDEOSETUP[] = { - &ME_VIDEOSETUP_RESOLUTION, -#ifdef USE_OPENGL - &ME_VIDEOSETUP_RENDERER, -#endif - &ME_VIDEOSETUP_FULLSCREEN, - &ME_VIDEOSETUP_VSYNC, - &ME_Space6_Redfont, - &ME_VIDEOSETUP_APPLY, -}; -static MenuEntry_t *MEL_DISPLAYSETUP[] = { - &ME_DISPLAYSETUP_SCREENSETUP, - &ME_DISPLAYSETUP_COLORCORR, -#ifndef EDUKE32_ANDROID_MENU - &ME_DISPLAYSETUP_VIDEOSETUP, - &ME_DISPLAYSETUP_ASPECTRATIO, - &ME_DISPLAYSETUP_VOXELS, - &ME_DISPLAYSETUP_FOV, -#endif -}; - -#ifdef USE_OPENGL -static MenuEntry_t *MEL_DISPLAYSETUP_GL[] = { - &ME_DISPLAYSETUP_SCREENSETUP, - &ME_DISPLAYSETUP_COLORCORR, - &ME_DISPLAYSETUP_VIDEOSETUP, - &ME_DISPLAYSETUP_ASPECTRATIO, - &ME_DISPLAYSETUP_VOXELS, - &ME_DISPLAYSETUP_FOV, - &ME_DISPLAYSETUP_TEXFILTER, - &ME_DISPLAYSETUP_ANISOTROPY, - &ME_DISPLAYSETUP_ADVANCED_GL_POLYMOST, -}; - - -#endif - - - -static char const *MenuKeyNone = " -"; -static char const *MEOSN_Keys[NUMKEYS]; - -static MenuCustom2Col_t MEO_KEYBOARDSETUPFUNCS_TEMPLATE = { { NULL, NULL, }, MEOSN_Keys, &MF_Minifont, NUMKEYS, 54<<16, 0 }; -static MenuCustom2Col_t MEO_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS]; -static MenuEntry_t ME_KEYBOARDSETUPFUNCS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_KBFuncList, &MEO_KEYBOARDSETUPFUNCS_TEMPLATE, Custom2Col ); -static MenuEntry_t ME_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS]; -static MenuEntry_t *MEL_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS]; - -static MenuLink_t MEO_KEYBOARDSETUP_KEYS = { MENU_KEYBOARDKEYS, MA_Advance, }; -static MenuEntry_t ME_KEYBOARDSETUP_KEYS = MAKE_MENUENTRY( "Edit Configuration", &MF_Redfont, &MEF_CenterMenu, &MEO_KEYBOARDSETUP_KEYS, Link ); -static MenuEntry_t ME_KEYBOARDSETUP_RESET = MAKE_MENUENTRY( "Reset To Defaults", &MF_Redfont, &MEF_CenterMenu, &MEO_NULL, Link ); -static MenuEntry_t ME_KEYBOARDSETUP_RESETCLASSIC = MAKE_MENUENTRY( "Reset To Classic", &MF_Redfont, &MEF_CenterMenu, &MEO_NULL, Link ); - -static MenuEntry_t *MEL_KEYBOARDSETUP[] = { - &ME_KEYBOARDSETUP_KEYS, - &ME_KEYBOARDSETUP_RESET, - &ME_KEYBOARDSETUP_RESETCLASSIC, -}; - - -// There is no better way to do this than manually. - -#define MENUMOUSEFUNCTIONS 12 - -static char const *MenuMouseNames[MENUMOUSEFUNCTIONS] = { - "Button 1", - "Double Button 1", - "Button 2", - "Double Button 2", - "Button 3", - "Double Button 3", - - "Wheel Up", - "Wheel Down", - - "Button 4", - "Double Button 4", - "Button 5", - "Double Button 5", -}; -static int32_t MenuMouseDataIndex[MENUMOUSEFUNCTIONS][2] = { - { 0, 0, }, - { 0, 1, }, - { 1, 0, }, - { 1, 1, }, - { 2, 0, }, - { 2, 1, }, - - // note the mouse wheel - { 4, 0, }, - { 5, 0, }, - - { 3, 0, }, - { 3, 1, }, - { 6, 0, }, - { 6, 1, }, -}; - -static MenuOption_t MEO_MOUSEJOYSETUPBTNS_TEMPLATE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL ); -static MenuOption_t MEO_MOUSESETUPBTNS[MENUMOUSEFUNCTIONS]; -static MenuEntry_t ME_MOUSEJOYSETUPBTNS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_FuncList, NULL, Option ); - -static MenuRangeFloat_t MEO_MOUSESETUP_SENSITIVITY = MAKE_MENURANGE( &in_mousesensitivity, &MF_Redfont, .5f, 16.f, 0.f, 32, 1 ); -static MenuEntry_t ME_MOUSESETUP_SENSITIVITY = MAKE_MENUENTRY( "Sensitivity:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_SENSITIVITY, RangeFloat ); - -#ifndef EDUKE32_SIMPLE_MENU -static char const *MEOSN_MOUSESETUP_AIM_TYPE [] = { "Toggle", "Hold" }; -static MenuOptionSet_t MEOS_MOUSESETUP_AIM_TYPE = MAKE_MENUOPTIONSET(MEOSN_MOUSESETUP_AIM_TYPE, NULL, 0x2); -static MenuOption_t MEO_MOUSESETUP_MOUSEAIMINGTYPE = MAKE_MENUOPTION(&MF_Redfont, &MEOS_MOUSESETUP_AIM_TYPE, &in_aimmode); -static MenuEntry_t ME_MOUSESETUP_MOUSEAIMINGTYPE = MAKE_MENUENTRY("Aiming type:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_MOUSEAIMINGTYPE, Option); -static MenuOption_t MEO_MOUSESETUP_MOUSEAIMING = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &in_mousemode ); -static MenuEntry_t ME_MOUSESETUP_MOUSEAIMING = MAKE_MENUENTRY( "Vertical aiming:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_MOUSEAIMING, Option ); -#endif -static MenuOption_t MEO_MOUSESETUP_INVERT = MAKE_MENUOPTION( &MF_Redfont, &MEOS_YesNo, &in_mouseflip ); -static MenuEntry_t ME_MOUSESETUP_INVERT = MAKE_MENUENTRY( "Invert aiming:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_INVERT, Option ); -static MenuOption_t MEO_MOUSESETUP_SMOOTH = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &in_mousesmoothing ); -static MenuEntry_t ME_MOUSESETUP_SMOOTH = MAKE_MENUENTRY( "Filter input:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_SMOOTH, Option ); -#ifndef EDUKE32_SIMPLE_MENU -static MenuLink_t MEO_MOUSESETUP_ADVANCED = { MENU_MOUSEADVANCED, MA_Advance, }; -static MenuEntry_t ME_MOUSESETUP_ADVANCED = MAKE_MENUENTRY( "Advanced setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_ADVANCED, Link ); -#endif -static MenuRangeInt32_t MEO_MOUSEADVANCED_SCALEX = MAKE_MENURANGE(&in_mousescalex, &MF_Redfont, -262144, 262144, 65536, 161, 3); -static MenuEntry_t ME_MOUSEADVANCED_SCALEX = MAKE_MENUENTRY("X-Scale:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSEADVANCED_SCALEX, RangeInt32); -static MenuRangeInt32_t MEO_MOUSEADVANCED_SCALEY = MAKE_MENURANGE(&in_mousescaley, &MF_Redfont, -262144, 262144, 65536, 161, 3); -static MenuEntry_t ME_MOUSEADVANCED_SCALEY = MAKE_MENUENTRY("Y-Scale:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSEADVANCED_SCALEY, RangeInt32); - -static MenuEntry_t *MEL_MOUSESETUP[] = { - &ME_MOUSESETUP_SENSITIVITY, -#ifdef EDUKE32_SIMPLE_MENU - &ME_MOUSEADVANCED_SCALEX, - &ME_MOUSEADVANCED_SCALEY, -#endif - &ME_Space2_Redfont, - &ME_MOUSESETUP_INVERT, - &ME_MOUSESETUP_SMOOTH, -#ifndef EDUKE32_SIMPLE_MENU - &ME_MOUSESETUP_MOUSEAIMINGTYPE, - &ME_MOUSESETUP_MOUSEAIMING, - &ME_MOUSESETUP_ADVANCED, -#endif -}; - -#ifdef EDUKE32_ANDROID_MENU -static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_MOVE = MAKE_MENURANGE(&droidinput.forward_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals); -static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_MOVE = MAKE_MENUENTRY("Running:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_MOVE, RangeFloat); - -static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_STRAFE = MAKE_MENURANGE(&droidinput.strafe_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals); -static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_STRAFE = MAKE_MENUENTRY("Strafing:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_STRAFE, RangeFloat); - -static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_LOOK = MAKE_MENURANGE(&droidinput.pitch_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals); -static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_LOOK = MAKE_MENUENTRY("Looking:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_LOOK, RangeFloat); - -static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_TURN = MAKE_MENURANGE(&droidinput.yaw_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals); -static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_TURN = MAKE_MENUENTRY("Turning:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_TURN, RangeFloat); - -static MenuOption_t MEO_TOUCHSETUP_INVERT = MAKE_MENUOPTION(&MF_Redfont, &MEOS_NoYes, &droidinput.invertLook); -static MenuEntry_t ME_TOUCHSETUP_INVERT = MAKE_MENUENTRY("Invert look:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_INVERT, Option); - -MAKE_MENU_TOP_ENTRYLINK("Sensitivity", MEF_CenterMenu, TOUCHSENS, MENU_TOUCHSENS); -MAKE_MENU_TOP_ENTRYLINK("Button Setup", MEF_CenterMenu, TOUCHBUTTONS, MENU_TOUCHBUTTONS); - -static MenuEntry_t *MEL_TOUCHSETUP [] = { - &ME_TOUCHSENS, - &ME_TOUCHBUTTONS, -}; - -static MenuEntry_t *MEL_TOUCHSENS [] = { - &ME_TOUCHSETUP_SENSITIVITY_MOVE, - &ME_TOUCHSETUP_SENSITIVITY_STRAFE, - &ME_TOUCHSETUP_SENSITIVITY_LOOK, - &ME_TOUCHSETUP_SENSITIVITY_TURN, - &ME_Space2_Redfont, - &ME_TOUCHSETUP_INVERT, -}; -#endif - -static MenuOption_t MEO_JOYSTICK_ENABLE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &in_joystick ); -static MenuEntry_t ME_JOYSTICK_ENABLE = MAKE_MENUENTRY( "Enable Gamepad:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_JOYSTICK_ENABLE, Option ); - -MAKE_MENU_TOP_ENTRYLINK( "Edit Buttons", MEF_CenterMenu, JOYSTICK_EDITBUTTONS, MENU_JOYSTICKBTNS ); -MAKE_MENU_TOP_ENTRYLINK( "Edit Axes", MEF_CenterMenu, JOYSTICK_EDITAXES, MENU_JOYSTICKAXES ); - -static MenuEntry_t *MEL_JOYSTICKSETUP[] = { - &ME_JOYSTICK_ENABLE, - &ME_Space6_Redfont, - &ME_JOYSTICK_EDITBUTTONS, - &ME_JOYSTICK_EDITAXES, -}; - -#define MAXJOYBUTTONSTRINGLENGTH 32 - -static char MenuJoystickNames[MAXJOYBUTTONSANDHATS*2][MAXJOYBUTTONSTRINGLENGTH]; - -static MenuOption_t MEO_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2]; -static MenuEntry_t ME_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2]; -static MenuEntry_t *MEL_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2]; - -static MenuLink_t MEO_JOYSTICKAXES = { MENU_JOYSTICKAXIS, MA_Advance, }; -static MenuEntry_t ME_JOYSTICKAXES_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXES, Link ); -static MenuEntry_t ME_JOYSTICKAXES[MAXJOYAXES]; -static char MenuJoystickAxes[MAXJOYAXES][MAXJOYBUTTONSTRINGLENGTH]; - -static MenuEntry_t *MEL_JOYSTICKAXES[MAXJOYAXES]; - -static MenuEntry_t *MEL_MOUSEADVANCED[] = { - &ME_MOUSEADVANCED_SCALEX, - &ME_MOUSEADVANCED_SCALEY, -}; - -static const char *MenuJoystickHatDirections[] = { "Up", "Right", "Down", "Left", }; - -static char const *MEOSN_JOYSTICKAXIS_ANALOG[] = { " -None-", "Turning", "Strafing", "Looking", "Moving", }; -static int32_t MEOSV_JOYSTICKAXIS_ANALOG[] = { -1, analog_turning, analog_strafing, analog_lookingupanddown, analog_moving, }; -static MenuOptionSet_t MEOS_JOYSTICKAXIS_ANALOG = MAKE_MENUOPTIONSET( MEOSN_JOYSTICKAXIS_ANALOG, MEOSV_JOYSTICKAXIS_ANALOG, 0x0 ); -static MenuOption_t MEO_JOYSTICKAXIS_ANALOG = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_JOYSTICKAXIS_ANALOG, NULL ); -static MenuEntry_t ME_JOYSTICKAXIS_ANALOG = MAKE_MENUENTRY( "Analog", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_ANALOG, Option ); -static MenuRangeInt32_t MEO_JOYSTICKAXIS_SCALE = MAKE_MENURANGE( NULL, &MF_Bluefont, -262144, 262144, 65536, 65, 3 ); -static MenuEntry_t ME_JOYSTICKAXIS_SCALE = MAKE_MENUENTRY( "Scale", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_SCALE, RangeInt32 ); -static MenuRangeInt32_t MEO_JOYSTICKAXIS_DEAD = MAKE_MENURANGE( NULL, &MF_Bluefont, 0, 1000000, 0, 33, 2 ); -static MenuEntry_t ME_JOYSTICKAXIS_DEAD = MAKE_MENUENTRY( "Dead Zone", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DEAD, RangeInt32 ); -static MenuRangeInt32_t MEO_JOYSTICKAXIS_SATU = MAKE_MENURANGE( NULL, &MF_Bluefont, 0, 1000000, 0, 33, 2 ); -static MenuEntry_t ME_JOYSTICKAXIS_SATU = MAKE_MENUENTRY( "Saturation", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_SATU, RangeInt32 ); - -static MenuOption_t MEO_JOYSTICKAXIS_DIGITALNEGATIVE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL ); -static MenuEntry_t ME_JOYSTICKAXIS_DIGITALNEGATIVE = MAKE_MENUENTRY( "Digital -", &MF_Bluefont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DIGITALNEGATIVE, Option ); -static MenuOption_t MEO_JOYSTICKAXIS_DIGITALPOSITIVE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL ); -static MenuEntry_t ME_JOYSTICKAXIS_DIGITALPOSITIVE = MAKE_MENUENTRY( "Digital +", &MF_Bluefont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DIGITALPOSITIVE, Option ); - -static MenuEntry_t *MEL_JOYSTICKAXIS[] = { - &ME_JOYSTICKAXIS_ANALOG, - &ME_JOYSTICKAXIS_SCALE, - &ME_JOYSTICKAXIS_DEAD, - &ME_JOYSTICKAXIS_SATU, - &ME_Space8_Redfont, - &ME_JOYSTICKAXIS_DIGITALNEGATIVE, - &ME_JOYSTICKAXIS_DIGITALPOSITIVE, -}; - -static MenuEntry_t *MEL_INTERNAL_JOYSTICKAXIS_DIGITAL[] = { - &ME_JOYSTICKAXIS_DIGITALNEGATIVE, - &ME_JOYSTICKAXIS_DIGITALPOSITIVE, -}; - -#ifdef USE_OPENGL -static MenuOption_t MEO_RENDERERSETUP_HIGHTILE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_hightile ); -static MenuEntry_t ME_RENDERERSETUP_HIGHTILE = MAKE_MENUENTRY( "True color textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_HIGHTILE, Option ); - -static MenuOption_t MEO_RENDERERSETUP_PRECACHE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &r_precache ); -static MenuEntry_t ME_RENDERERSETUP_PRECACHE = MAKE_MENUENTRY( "Pre-load map textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_PRECACHE, Option ); -# ifndef EDUKE32_GLES -static char const *MEOSN_RENDERERSETUP_TEXCACHE[] = { "Off", "On", "Compr.", }; -static MenuOptionSet_t MEOS_RENDERERSETUP_TEXCACHE = MAKE_MENUOPTIONSET( MEOSN_RENDERERSETUP_TEXCACHE, NULL, 0x2 ); -# endif -# ifdef USE_GLEXT -static MenuOption_t MEO_RENDERERSETUP_DETAILTEX = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_detailmapping); -static MenuEntry_t ME_RENDERERSETUP_DETAILTEX = MAKE_MENUENTRY( "Detail textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_DETAILTEX, Option ); -static MenuOption_t MEO_RENDERERSETUP_GLOWTEX = MAKE_MENUOPTION(&MF_Bluefont, &MEOS_NoYes, &hw_glowmapping); -static MenuEntry_t ME_RENDERERSETUP_GLOWTEX = MAKE_MENUENTRY("Glow textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_GLOWTEX, Option); -# endif -static MenuOption_t MEO_RENDERERSETUP_MODELS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_models ); -static MenuEntry_t ME_RENDERERSETUP_MODELS = MAKE_MENUENTRY( "3D models:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_MODELS, Option ); -#endif - - -#ifdef USE_OPENGL -static MenuEntry_t *MEL_RENDERERSETUP_POLYMOST[] = { - &ME_RENDERERSETUP_HIGHTILE, - &ME_RENDERERSETUP_PRECACHE, -# ifdef USE_GLEXT - &ME_RENDERERSETUP_DETAILTEX, - &ME_RENDERERSETUP_GLOWTEX, -# endif - &ME_Space4_Bluefont, - &ME_RENDERERSETUP_MODELS, -}; - -#endif - -#ifdef EDUKE32_ANDROID_MENU -static MenuRangeFloat_t MEO_COLCORR_GAMMA = MAKE_MENURANGE( &vid_gamma, &MF_Bluefont, 1.f, 2.5f, 0.f, 39, 1 ); -#else -static MenuRangeFloat_t MEO_COLCORR_GAMMA = MAKE_MENURANGE( &vid_gamma, &MF_Bluefont, 0.3f, 4.f, 0.f, 38, 1 ); -#endif -static MenuEntry_t ME_COLCORR_GAMMA = MAKE_MENUENTRY( "Gamma:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_GAMMA, RangeFloat ); -static MenuRangeFloat_t MEO_COLCORR_CONTRAST = MAKE_MENURANGE( &vid_contrast, &MF_Bluefont, 0.1f, 2.7f, 0.f, 53, 1 ); -static MenuEntry_t ME_COLCORR_CONTRAST = MAKE_MENUENTRY( "Contrast:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_CONTRAST, RangeFloat ); -static MenuRangeFloat_t MEO_COLCORR_BRIGHTNESS = MAKE_MENURANGE( &vid_brightness, &MF_Bluefont, -0.8f, 0.8f, 0.f, 33, 1 ); -static MenuEntry_t ME_COLCORR_BRIGHTNESS = MAKE_MENUENTRY( "Brightness:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_BRIGHTNESS, RangeFloat ); -static MenuEntry_t ME_COLCORR_RESET = MAKE_MENUENTRY( "Reset To Defaults", &MF_Redfont, &MEF_ColorCorrect, &MEO_NULL, Link ); -#ifdef EDUKE32_ANDROID_MENU -#define MINVIS 1.f -#else -#define MINVIS 0.125f -#endif -#ifndef EDUKE32_SIMPLE_MENU -static MenuRangeFloat_t MEO_COLCORR_AMBIENT = MAKE_MENURANGE( &r_ambientlight, &MF_Bluefont, MINVIS, 4.f, 0.f, 32, 1 ); -static MenuEntry_t ME_COLCORR_AMBIENT = MAKE_MENUENTRY( "Visibility:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_AMBIENT, RangeFloat ); -#endif -static MenuEntry_t *MEL_COLCORR[] = { - &ME_COLCORR_GAMMA, -#ifndef EDUKE32_ANDROID_MENU - &ME_COLCORR_CONTRAST, - &ME_COLCORR_BRIGHTNESS, -#endif -#ifndef EDUKE32_SIMPLE_MENU - &ME_COLCORR_AMBIENT, -#endif - &ME_Space8_Redfont, - &ME_COLCORR_RESET, -}; - -static MenuEntry_t *MEL_SCREENSETUP[] = { -#ifdef EDUKE32_ANDROID_MENU - &ME_SCREENSETUP_STATUSBARONTOP, -#endif - &ME_SCREENSETUP_SCREENSIZE, - &ME_SCREENSETUP_SBARSIZE, - - &ME_SCREENSETUP_CROSSHAIR, - &ME_SCREENSETUP_CROSSHAIRSIZE, - - &ME_SCREENSETUP_LEVELSTATS, - &ME_SCREENSETUP_TEXTSIZE, - - &ME_SCREENSETUP_SHOWPICKUPMESSAGES, -}; - -// Save and load will be filled in before every viewing of the save/load screen. -static MenuLink_t MEO_LOAD = { MENU_LOADVERIFY, MA_None, }; -static MenuEntry_t ME_LOAD_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, &MEO_LOAD, Link ); -static MenuEntry_t ME_LOAD_EMPTY = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, nullptr, Dummy ); -static MenuEntry_t *ME_LOAD; -static MenuEntry_t **MEL_LOAD; - -static char const s_NewSaveGame[] = "(New Save Game)"; -static MenuString_t MEO_SAVE_TEMPLATE = MAKE_MENUSTRING( NULL, &MF_Minifont, MAXSAVEGAMENAME, 0 ); -static MenuString_t MEO_SAVE_NEW = MAKE_MENUSTRING( NULL, &MF_Minifont, MAXSAVEGAMENAME, 0 ); -static MenuString_t *MEO_SAVE; -static MenuEntry_t ME_SAVE_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, &MEO_SAVE_TEMPLATE, String ); -static MenuEntry_t ME_SAVE_NEW = MAKE_MENUENTRY( s_NewSaveGame, &MF_Minifont, &MEF_LoadSave, &MEO_SAVE_NEW, String ); -static MenuEntry_t *ME_SAVE; -static MenuEntry_t **MEL_SAVE; - -CVAR_UNAMED(Int, soundrate) -CVAR_UNAMED(Int, soundvoices) -CVAR_UNAMED(Int, musicdevice) -static MenuOption_t MEO_SOUND = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &snd_enabled ); -static MenuEntry_t ME_SOUND = MAKE_MENUENTRY( "Sound:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND, Option ); - -static MenuOption_t MEO_SOUND_MUSIC = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &mus_enabled ); -static MenuEntry_t ME_SOUND_MUSIC = MAKE_MENUENTRY( "Music:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_MUSIC, Option ); - -static MenuLink_t MEO_SOUND_CDPLAYER = { MENU_CDPLAYER, MA_Advance, }; -static MenuEntry_t ME_SOUND_CDPLAYER = MAKE_MENUENTRY( "8 Track Player", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_CDPLAYER, Link ); - -static MenuRangeInt32_t MEO_SOUND_VOLUME_FX = MAKE_MENURANGE( &snd_fxvolume, &MF_Redfont, 0, 255, 0, 33, 2 ); -static MenuEntry_t ME_SOUND_VOLUME_FX = MAKE_MENUENTRY( "Volume:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_VOLUME_FX, RangeInt32 ); - -static MenuRangeInt32_t MEO_SOUND_VOLUME_MUSIC = MAKE_MENURANGE( &mus_volume, &MF_Redfont, 0, 255, 0, 33, 2 ); -static MenuEntry_t ME_SOUND_VOLUME_MUSIC = MAKE_MENUENTRY( "Music:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_VOLUME_MUSIC, RangeInt32 ); - -static MenuOption_t MEO_SOUND_DUKETALK = MAKE_MENUOPTION(&MF_Redfont, &MEOS_NoYes, NULL); -static MenuEntry_t ME_SOUND_DUKETALK = MAKE_MENUENTRY( "Duke talk:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_DUKETALK, Option ); - -static char const *MEOSN_SOUND_SAMPLINGRATE[] = { "22050Hz", "44100Hz", "48000Hz", }; -static int32_t MEOSV_SOUND_SAMPLINGRATE[] = { 22050, 44100, 48000, }; -static MenuOptionSet_t MEOS_SOUND_SAMPLINGRATE = MAKE_MENUOPTIONSET( MEOSN_SOUND_SAMPLINGRATE, MEOSV_SOUND_SAMPLINGRATE, 0x3 ); -static MenuOption_t MEO_SOUND_SAMPLINGRATE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_SOUND_SAMPLINGRATE, &soundrate ); -static MenuEntry_t ME_SOUND_SAMPLINGRATE = MAKE_MENUENTRY( "Sample rate:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_SAMPLINGRATE, Option ); - -#ifndef EDUKE32_SIMPLE_MENU -static MenuRangeInt32_t MEO_SOUND_NUMVOICES = MAKE_MENURANGE( &soundvoices, &MF_Redfont, 16, 256, 0, 16, 1 ); -static MenuEntry_t ME_SOUND_NUMVOICES = MAKE_MENUENTRY( "Voices:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_NUMVOICES, RangeInt32 ); -#endif - -static char const *MEOSN_SOUND_MIDIDRIVER[] = { - "OPL3", -#ifdef _WIN32 - "Windows", -#endif -}; -static int32_t MEOSV_SOUND_MIDIDRIVER[] = { - ASS_OPL3, -#ifdef _WIN32 - ASS_WinMM, -#endif -}; - -static MenuOptionSet_t MEOS_SOUND_MIDIDRIVER = MAKE_MENUOPTIONSET( MEOSN_SOUND_MIDIDRIVER, MEOSV_SOUND_MIDIDRIVER, 0x2 ); -static MenuOption_t MEO_SOUND_MIDIDRIVER = MAKE_MENUOPTION( &MF_Redfont, &MEOS_SOUND_MIDIDRIVER, &musicdevice ); -static MenuEntry_t ME_SOUND_MIDIDRIVER = MAKE_MENUENTRY( "MIDI driver:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_MIDIDRIVER, Option ); - -static MenuEntry_t ME_SOUND_RESTART = MAKE_MENUENTRY( "Apply Changes", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_NULL, Link ); - -#ifndef EDUKE32_SIMPLE_MENU -static MenuLink_t MEO_ADVSOUND = { MENU_ADVSOUND, MA_Advance, }; -static MenuEntry_t ME_SOUND_ADVSOUND = MAKE_MENUENTRY( "Advanced", &MF_Redfont, &MEF_BigOptionsRt, &MEO_ADVSOUND, Link ); -#endif - -static MenuEntry_t *MEL_SOUND[] = { - &ME_SOUND, - &ME_SOUND_VOLUME_FX, - &ME_SOUND_MUSIC, - &ME_SOUND_VOLUME_MUSIC, - &ME_SOUND_DUKETALK, -#ifndef EDUKE32_SIMPLE_MENU - &ME_SOUND_ADVSOUND, -#endif -}; - -static MenuEntry_t *MEL_ADVSOUND[] = { - &ME_SOUND_SAMPLINGRATE, - &ME_Space2_Redfont, -#ifndef EDUKE32_SIMPLE_MENU - &ME_SOUND_NUMVOICES, - &ME_Space2_Redfont, -#endif - &ME_SOUND_MIDIDRIVER, - &ME_SOUND_RESTART, -}; - -static MenuEntry_t ME_CDPLAYER_TRACK = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_NULL, Dummy); - -static MenuEntry_t *MEL_CDPLAYER[] = { - &ME_CDPLAYER_TRACK, - &ME_CDPLAYER_TRACK, - &ME_CDPLAYER_TRACK, - &ME_CDPLAYER_TRACK, - &ME_CDPLAYER_TRACK, - &ME_CDPLAYER_TRACK, - &ME_CDPLAYER_TRACK, - &ME_CDPLAYER_TRACK -}; - - -static MenuOption_t MEO_SAVESETUP_AUTOSAVE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &cl_autosave ); -static MenuEntry_t ME_SAVESETUP_AUTOSAVE = MAKE_MENUENTRY( "Autosaves:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SAVESETUP_AUTOSAVE, Option ); - -static MenuOption_t MEO_SAVESETUP_AUTOSAVEDELETION = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &cl_autosavedeletion ); -static MenuEntry_t ME_SAVESETUP_AUTOSAVEDELETION = MAKE_MENUENTRY( "Auto-Delete:", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SAVESETUP_AUTOSAVEDELETION, Option ); -static MenuRangeInt32_t MEO_SAVESETUP_MAXAUTOSAVES = MAKE_MENURANGE( &cl_maxautosaves, &MF_Redfont, 1, 10, 0, 10, 1 ); -static MenuEntry_t ME_SAVESETUP_MAXAUTOSAVES = MAKE_MENUENTRY( "Limit:", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SAVESETUP_MAXAUTOSAVES, RangeInt32 ); - -static MenuEntry_t ME_SAVESETUP_CLEANUP = MAKE_MENUENTRY( "Clean Up Saves", &MF_Redfont, &MEF_BigOptionsRt, &MEO_NULL, Link ); - -static MenuEntry_t *MEL_SAVESETUP[] = { - &ME_SAVESETUP_AUTOSAVE, - &ME_SAVESETUP_AUTOSAVEDELETION, - &ME_SAVESETUP_MAXAUTOSAVES, - &ME_SAVESETUP_CLEANUP, -}; - - -MAKE_MENU_TOP_ENTRYLINK( "Player Setup", MEF_CenterMenu, NETWORK_PLAYERSETUP, MENU_PLAYER ); -MAKE_MENU_TOP_ENTRYLINK( "Join Game", MEF_CenterMenu, NETWORK_JOINGAME, MENU_NETJOIN ); -MAKE_MENU_TOP_ENTRYLINK( "Host Game", MEF_CenterMenu, NETWORK_HOSTGAME, MENU_NETHOST ); - -static MenuEntry_t *MEL_NETWORK[] = { - &ME_NETWORK_PLAYERSETUP, - &ME_NETWORK_JOINGAME, - &ME_NETWORK_HOSTGAME, -}; - -//static MenuString_t MEO_PLAYER_NAME = MAKE_MENUSTRING( playername, &MF_Bluefont, MAXPLAYERNAME, 0 ); -//static MenuEntry_t ME_PLAYER_NAME = MAKE_MENUENTRY( "Name", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_NAME, String ); -static char const *MEOSN_PLAYER_COLOR[] = { "Auto", "Blue", "Red", "Green", "Gray", "Dark gray", "Dark green", "Brown", "Dark blue", "Bright red", "Yellow", }; -static int32_t MEOSV_PLAYER_COLOR[] = { 0, 9, 10, 11, 12, 13, 14, 15, 16, 21, 23, }; -static MenuOptionSet_t MEOS_PLAYER_COLOR = MAKE_MENUOPTIONSET( MEOSN_PLAYER_COLOR, MEOSV_PLAYER_COLOR, 0x2 ); -static MenuOption_t MEO_PLAYER_COLOR = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_PLAYER_COLOR, &playercolor ); -static MenuEntry_t ME_PLAYER_COLOR = MAKE_MENUENTRY( "Color", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_COLOR, Option ); -static char const *MEOSN_PLAYER_TEAM[] = { "Blue", "Red", "Green", "Gray", }; -static MenuOptionSet_t MEOS_PLAYER_TEAM = MAKE_MENUOPTIONSET( MEOSN_PLAYER_TEAM, NULL, 0x2 ); -static MenuOption_t MEO_PLAYER_TEAM = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_PLAYER_TEAM, &playerteam ); -static MenuEntry_t ME_PLAYER_TEAM = MAKE_MENUENTRY( "Team", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_TEAM, Option ); -#ifndef EDUKE32_SIMPLE_MENU -static MenuLink_t MEO_PLAYER_MACROS = { MENU_MACROS, MA_Advance, }; -static MenuEntry_t ME_PLAYER_MACROS = MAKE_MENUENTRY( "Multiplayer macros", &MF_Bluefont, &MEF_SmallOptions, &MEO_PLAYER_MACROS, Link ); -#endif - -static MenuEntry_t *MEL_PLAYER[] = { - //&ME_PLAYER_NAME, - &ME_Space4_Bluefont, - &ME_PLAYER_COLOR, - &ME_Space4_Bluefont, - &ME_PLAYER_TEAM, -#ifndef EDUKE32_SIMPLE_MENU - &ME_Space8_Bluefont, - &ME_PLAYER_MACROS, -#endif -}; - -#define MAXRIDECULE 10 -#define MAXRIDECULELENGTH 40 -static MenuString_t MEO_MACROS_TEMPLATE = MAKE_MENUSTRING( NULL, &MF_Bluefont, MAXRIDECULELENGTH, 0 ); -static MenuString_t MEO_MACROS[10]; -static char sink[50]; -static MenuEntry_t ME_MACROS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Macros, &MEO_MACROS_TEMPLATE, String ); -static MenuEntry_t ME_MACROS[MAXRIDECULE]; -static MenuEntry_t *MEL_MACROS[MAXRIDECULE]; - -#ifndef EDUKE32_SIMPLE_MENU -static char const *MenuUserMap = "User Map"; -#endif -static char const *MenuSkillNone = "None"; - -static char const *MEOSN_NetGametypes[MAXGAMETYPES]; -static char const *MEOSN_NetEpisodes[MAXVOLUMES+1]; -static int32_t MEOSV_NetEpisodes[MAXVOLUMES+1]; -static char const *MEOSN_NetLevels[MAXVOLUMES][MAXLEVELS]; -static char const *MEOSN_NetSkills[MAXSKILLS+1]; - -static MenuLink_t MEO_NETHOST_OPTIONS = { MENU_NETOPTIONS, MA_Advance, }; -static MenuEntry_t ME_NETHOST_OPTIONS = MAKE_MENUENTRY( "Game Options", &MF_Redfont, &MEF_VideoSetup, &MEO_NETHOST_OPTIONS, Link ); -static MenuEntry_t ME_NETHOST_LAUNCH = MAKE_MENUENTRY( "Launch Game", &MF_Redfont, &MEF_VideoSetup, &MEO_NULL, Link ); - -static MenuEntry_t *MEL_NETHOST[] = { - &ME_NETHOST_OPTIONS, - &ME_NETHOST_LAUNCH, -}; - -static MenuOptionSet_t MEOS_NETOPTIONS_GAMETYPE = MAKE_MENUOPTIONSET( MEOSN_NetGametypes, NULL, 0x0 ); -static MenuOption_t MEO_NETOPTIONS_GAMETYPE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_GAMETYPE, &m_coop ); -static MenuEntry_t ME_NETOPTIONS_GAMETYPE = MAKE_MENUENTRY( "Game Type", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_GAMETYPE, Option ); -static MenuOptionSet_t MEOS_NETOPTIONS_EPISODE = MAKE_MENUOPTIONSET( MEOSN_NetEpisodes, MEOSV_NetEpisodes, 0x0 ); -CVAR_UNAMED(Int, NetEpisode); -static MenuOption_t MEO_NETOPTIONS_EPISODE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_EPISODE, &NetEpisode ); -static MenuEntry_t ME_NETOPTIONS_EPISODE = MAKE_MENUENTRY( "Episode", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_EPISODE, Option ); -static MenuOptionSet_t MEOS_NETOPTIONS_LEVEL_TEMPLATE = MAKE_MENUOPTIONSETNULL; -static MenuOptionSet_t MEOS_NETOPTIONS_LEVEL[MAXVOLUMES]; -static MenuOption_t MEO_NETOPTIONS_LEVEL = MAKE_MENUOPTION( &MF_Bluefont, NULL, &m_level_number ); -static MenuEntry_t ME_NETOPTIONS_LEVEL = MAKE_MENUENTRY( "Level", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_LEVEL, Option ); -static MenuLink_t MEO_NETOPTIONS_USERMAP = { MENU_NETUSERMAP, MA_Advance, }; -static MenuEntry_t ME_NETOPTIONS_USERMAP = MAKE_MENUENTRY( "User Map", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_USERMAP, Link ); -static MenuOptionSet_t MEOS_NETOPTIONS_MONSTERS = MAKE_MENUOPTIONSET( MEOSN_NetSkills, NULL, 0x0 ); -static MenuOption_t MEO_NETOPTIONS_MONSTERS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_MONSTERS, NULL ); -static MenuEntry_t ME_NETOPTIONS_MONSTERS = MAKE_MENUENTRY( "Monsters", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MONSTERS, Option ); -static MenuOption_t MEO_NETOPTIONS_MARKERS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &m_marker); -static MenuEntry_t ME_NETOPTIONS_MARKERS = MAKE_MENUENTRY( "Markers", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MARKERS, Option ); -static MenuOption_t MEO_NETOPTIONS_MAPEXITS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OnOff, &m_noexits); -static MenuEntry_t ME_NETOPTIONS_MAPEXITS = MAKE_MENUENTRY( "Map Exits", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MAPEXITS, Option ); -static MenuOption_t MEO_NETOPTIONS_FRFIRE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &m_ffire); -static MenuEntry_t ME_NETOPTIONS_FRFIRE = MAKE_MENUENTRY( "Fr. Fire", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_FRFIRE, Option ); -static MenuEntry_t ME_NETOPTIONS_ACCEPT = MAKE_MENUENTRY( "Accept", &MF_Redfont, &MEF_NetSetup_Confirm, &MEO_NETWORK_HOSTGAME, Link ); - -static MenuEntry_t *MEL_NETOPTIONS[] = { - &ME_NETOPTIONS_GAMETYPE, - &ME_NETOPTIONS_EPISODE, - &ME_NETOPTIONS_LEVEL, - &ME_NETOPTIONS_MONSTERS, - &ME_NETOPTIONS_MARKERS, - &ME_NETOPTIONS_MAPEXITS, - &ME_NETOPTIONS_ACCEPT, -}; - -static char MenuServer[BMAX_PATH] = "localhost"; -static MenuString_t MEO_NETJOIN_SERVER = MAKE_MENUSTRING( MenuServer, &MF_Bluefont, BMAX_PATH, 0 ); -static MenuEntry_t ME_NETJOIN_SERVER = MAKE_MENUENTRY( "Server", &MF_Redfont, &MEF_VideoSetup, &MEO_NETJOIN_SERVER, String ); -#define MAXPORTSTRINGLENGTH 6 // unsigned 16-bit integer -static char MenuPort[MAXPORTSTRINGLENGTH] = "19014"; -static MenuString_t MEO_NETJOIN_PORT = MAKE_MENUSTRING( MenuPort, &MF_Bluefont, MAXPORTSTRINGLENGTH, INPUT_NUMERIC ); -static MenuEntry_t ME_NETJOIN_PORT = MAKE_MENUENTRY( "Port", &MF_Redfont, &MEF_VideoSetup, &MEO_NETJOIN_PORT, String ); -static MenuEntry_t ME_NETJOIN_CONNECT = MAKE_MENUENTRY( "Connect", &MF_Redfont, &MEF_VideoSetup_Apply, &MEO_NULL, Link ); - -static MenuEntry_t *MEL_NETJOIN[] = { - &ME_NETJOIN_SERVER, - &ME_NETJOIN_PORT, - &ME_NETJOIN_CONNECT, -}; - - -#define NoTitle NULL - -#define MAKE_MENUMENU(Title, Format, Entries) { Title, Format, Entries, ARRAY_SIZE(Entries), 0, 0, 0 } -#define MAKE_MENUMENU_CUSTOMSIZE(Title, Format, Entries) { Title, Format, Entries, 0, 0, 0, 0 } - -static MenuMenu_t M_MAIN = MAKE_MENUMENU( NoTitle, &MMF_Top_Main, MEL_MAIN ); -static MenuMenu_t M_MAIN_INGAME = MAKE_MENUMENU( NoTitle, &MMF_Top_Main, MEL_MAIN_INGAME ); -static MenuMenu_t M_EPISODE = MAKE_MENUMENU( "Select An Episode", &MMF_Top_Episode, MEL_EPISODE ); -static MenuMenu_t M_SKILL = MAKE_MENUMENU( "Select Skill", &MMF_Top_Skill, MEL_SKILL ); -#ifndef EDUKE32_SIMPLE_MENU -static MenuMenu_t M_GAMESETUP = MAKE_MENUMENU( "Game Setup", &MMF_BigOptions, MEL_GAMESETUP ); -#endif -static MenuMenu_t M_OPTIONS = MAKE_MENUMENU( s_Options, &MMF_Top_Options, MEL_OPTIONS ); -static MenuMenu_t M_VIDEOSETUP = MAKE_MENUMENU( "Video Mode", &MMF_BigOptions, MEL_VIDEOSETUP ); -static MenuMenu_t M_KEYBOARDSETUP = MAKE_MENUMENU( "Configure Controls", &MMF_Top_Options, MEL_KEYBOARDSETUP ); -static MenuMenu_t M_CONTROLS = MAKE_MENUMENU( "Control Setup", &MMF_Top_Options, MEL_CONTROLS ); -static MenuMenu_t M_CHEATS = MAKE_MENUMENU( "Cheats", &MMF_SmallOptions, MEL_CHEATS ); -static MenuMenu_t M_MOUSESETUP = MAKE_MENUMENU( "Mouse Setup", &MMF_BigOptions, MEL_MOUSESETUP ); -#ifdef EDUKE32_ANDROID_MENU -static MenuMenu_t M_TOUCHSETUP = MAKE_MENUMENU( "Touch Setup", &MMF_Top_Options, MEL_TOUCHSETUP ); -static MenuMenu_t M_TOUCHSENS = MAKE_MENUMENU( "Sensitivity", &MMF_BigOptions, MEL_TOUCHSENS); -static MenuPanel_t M_TOUCHBUTTONS = { "Button Setup", MENU_TOUCHSETUP, MA_Return, MENU_TOUCHSETUP, MA_Advance, }; -#endif -static MenuMenu_t M_JOYSTICKSETUP = MAKE_MENUMENU( "Joystick Setup", &MMF_Top_Joystick_Network, MEL_JOYSTICKSETUP ); -static MenuMenu_t M_JOYSTICKBTNS = MAKE_MENUMENU( "Joystick Buttons", &MMF_MouseJoySetupBtns, MEL_JOYSTICKBTNS ); -static MenuMenu_t M_JOYSTICKAXES = MAKE_MENUMENU( "Joystick Axes", &MMF_BigSliders, MEL_JOYSTICKAXES ); -static MenuMenu_t M_KEYBOARDKEYS = MAKE_MENUMENU( "Key Configuration", &MMF_KeyboardSetupFuncs, MEL_KEYBOARDSETUPFUNCS ); -static MenuMenu_t M_MOUSEADVANCED = MAKE_MENUMENU( "Advanced Mouse", &MMF_BigSliders, MEL_MOUSEADVANCED ); -static MenuMenu_t M_JOYSTICKAXIS = MAKE_MENUMENU( NULL, &MMF_BigSliders, MEL_JOYSTICKAXIS ); -#ifdef USE_OPENGL -static MenuMenu_t M_RENDERERSETUP_POLYMOST = MAKE_MENUMENU( "Polymost Setup", &MMF_SmallOptions, MEL_RENDERERSETUP_POLYMOST ); -# ifdef POLYMER -static MenuMenu_t M_RENDERERSETUP_POLYMER = MAKE_MENUMENU("Polymer Setup", &MMF_SmallOptions, MEL_RENDERERSETUP_POLYMER ); -# endif -#endif -static MenuMenu_t M_COLCORR = MAKE_MENUMENU( "Color Correction", &MMF_ColorCorrect, MEL_COLCORR ); -static MenuMenu_t M_SCREENSETUP = MAKE_MENUMENU( "HUD Setup", &MMF_BigOptions, MEL_SCREENSETUP ); -static MenuMenu_t M_DISPLAYSETUP = MAKE_MENUMENU( "Display Setup", &MMF_BigOptions, MEL_DISPLAYSETUP ); -static MenuMenu_t M_LOAD = MAKE_MENUMENU_CUSTOMSIZE( s_LoadGame, &MMF_LoadSave, MEL_LOAD ); -static MenuMenu_t M_SAVE = MAKE_MENUMENU_CUSTOMSIZE( s_SaveGame, &MMF_LoadSave, MEL_SAVE ); -static MenuMenu_t M_SOUND = MAKE_MENUMENU( "Sound Setup", &MMF_BigOptions, MEL_SOUND ); -static MenuMenu_t M_ADVSOUND = MAKE_MENUMENU( "Advanced Sound", &MMF_BigOptions, MEL_ADVSOUND ); -static MenuMenu_t M_CDPLAYER = MAKE_MENUMENU( "8 Track Player", &MMF_BigOptions, MEL_CDPLAYER ); -static MenuMenu_t M_SAVESETUP = MAKE_MENUMENU( "Save Setup", &MMF_BigOptions, MEL_SAVESETUP ); -static MenuMenu_t M_NETWORK = MAKE_MENUMENU( "Network Game", &MMF_Top_Joystick_Network, MEL_NETWORK ); -static MenuMenu_t M_PLAYER = MAKE_MENUMENU( "Player Setup", &MMF_SmallOptions, MEL_PLAYER ); -static MenuMenu_t M_MACROS = MAKE_MENUMENU( "Multiplayer Macros", &MMF_Macros, MEL_MACROS ); -static MenuMenu_t M_NETHOST = MAKE_MENUMENU( "Host Network Game", &MMF_SmallOptionsNarrow, MEL_NETHOST ); -static MenuMenu_t M_NETOPTIONS = MAKE_MENUMENU( "Net Game Options", &MMF_NetSetup, MEL_NETOPTIONS ); -static MenuMenu_t M_NETJOIN = MAKE_MENUMENU( "Join Network Game", &MMF_SmallOptionsNarrow, MEL_NETJOIN ); - -#ifdef EDUKE32_SIMPLE_MENU -static MenuPanel_t M_STORY = { NoTitle, MENU_STORY, MA_Return, MENU_STORY, MA_Advance, }; -#else -static MenuPanel_t M_STORY = { NoTitle, MENU_F1HELP, MA_Return, MENU_F1HELP, MA_Advance, }; -#endif - -static MenuPanel_t M_F1HELP = { NoTitle, MENU_STORY, MA_Return, MENU_STORY, MA_Advance, }; -static MenuPanel_t M_F1HELP2 = { NoTitle, MENU_F1HELP, MA_Return, MENU_STORY, MA_Advance, }; -static MenuPanel_t M_CREDITS = { NoTitle, MENU_CREDITS33, MA_Return, MENU_CREDITS2, MA_Advance, }; -static MenuPanel_t M_CREDITS2 = { NoTitle, MENU_CREDITS, MA_Return, MENU_CREDITS3, MA_Advance, }; -static MenuPanel_t M_CREDITS3 = { NoTitle, MENU_CREDITS2, MA_Return, MENU_CREDITS31, MA_Advance, }; -static MenuPanel_t M_CREDITS4 = { s_Credits, MENU_CREDITS3, MA_Return, MENU_CREDITS5, MA_Advance, }; -static MenuPanel_t M_CREDITS5 = { s_Credits, MENU_CREDITS4, MA_Return, MENU_CREDITS6, MA_Advance, }; -static MenuPanel_t M_CREDITS6 = { s_Credits, MENU_CREDITS5, MA_Return, MENU_CREDITS7, MA_Advance, }; -static MenuPanel_t M_CREDITS7 = { s_Credits, MENU_CREDITS6, MA_Return, MENU_CREDITS8, MA_Advance, }; -static MenuPanel_t M_CREDITS8 = { s_Credits, MENU_CREDITS7, MA_Return, MENU_CREDITS9, MA_Advance, }; -static MenuPanel_t M_CREDITS9 = { s_Credits, MENU_CREDITS8, MA_Return, MENU_CREDITS10, MA_Advance, }; -static MenuPanel_t M_CREDITS10 = { s_Credits, MENU_CREDITS9, MA_Return, MENU_CREDITS11, MA_Advance, }; -static MenuPanel_t M_CREDITS11 = { s_Credits, MENU_CREDITS10, MA_Return, MENU_CREDITS12, MA_Advance, }; -static MenuPanel_t M_CREDITS12 = { s_Credits, MENU_CREDITS11, MA_Return, MENU_CREDITS13, MA_Advance, }; -static MenuPanel_t M_CREDITS13 = { s_Credits, MENU_CREDITS12, MA_Return, MENU_CREDITS14, MA_Advance, }; -static MenuPanel_t M_CREDITS14 = { s_Credits, MENU_CREDITS13, MA_Return, MENU_CREDITS15, MA_Advance, }; -static MenuPanel_t M_CREDITS15 = { s_Credits, MENU_CREDITS14, MA_Return, MENU_CREDITS16, MA_Advance, }; -static MenuPanel_t M_CREDITS16 = { s_Credits, MENU_CREDITS15, MA_Return, MENU_CREDITS17, MA_Advance, }; -static MenuPanel_t M_CREDITS17 = { s_Credits, MENU_CREDITS16, MA_Return, MENU_CREDITS18, MA_Advance, }; -static MenuPanel_t M_CREDITS18 = { s_Credits, MENU_CREDITS17, MA_Return, MENU_CREDITS19, MA_Advance, }; -static MenuPanel_t M_CREDITS19 = { s_Credits, MENU_CREDITS18, MA_Return, MENU_CREDITS20, MA_Advance, }; -static MenuPanel_t M_CREDITS20 = { s_Credits, MENU_CREDITS19, MA_Return, MENU_CREDITS21, MA_Advance, }; -static MenuPanel_t M_CREDITS21 = { s_Credits, MENU_CREDITS20, MA_Return, MENU_CREDITS22, MA_Advance, }; -static MenuPanel_t M_CREDITS22 = { s_Credits, MENU_CREDITS21, MA_Return, MENU_CREDITS23, MA_Advance, }; -static MenuPanel_t M_CREDITS23 = { s_Credits, MENU_CREDITS22, MA_Return, MENU_CREDITS24, MA_Advance, }; -static MenuPanel_t M_CREDITS24 = { s_Credits, MENU_CREDITS23, MA_Return, MENU_CREDITS25, MA_Advance, }; -static MenuPanel_t M_CREDITS25 = { s_Credits, MENU_CREDITS24, MA_Return, MENU_CREDITS26, MA_Advance, }; -static MenuPanel_t M_CREDITS26 = { s_Credits, MENU_CREDITS25, MA_Return, MENU_CREDITS27, MA_Advance, }; -static MenuPanel_t M_CREDITS27 = { s_Credits, MENU_CREDITS26, MA_Return, MENU_CREDITS28, MA_Advance, }; -static MenuPanel_t M_CREDITS28 = { s_Credits, MENU_CREDITS27, MA_Return, MENU_CREDITS29, MA_Advance, }; -static MenuPanel_t M_CREDITS29 = { s_Credits, MENU_CREDITS28, MA_Return, MENU_CREDITS30, MA_Advance, }; -static MenuPanel_t M_CREDITS30 = { s_Credits, MENU_CREDITS29, MA_Return, MENU_CREDITS31, MA_Advance, }; -static MenuPanel_t M_CREDITS31 = { "About " APPNAME, MENU_CREDITS3, MA_Return, MENU_CREDITS32, MA_Advance, }; -static MenuPanel_t M_CREDITS32 = { "About EDuke32", MENU_CREDITS31, MA_Return, MENU_CREDITS33, MA_Advance, }; -static MenuPanel_t M_CREDITS33 = { "About EDuke32", MENU_CREDITS32, MA_Return, MENU_CREDITS, MA_Advance, }; - -#define CURSOR_CENTER_2LINE { MENU_MARGIN_CENTER<<16, 120<<16, } -#define CURSOR_CENTER_3LINE { MENU_MARGIN_CENTER<<16, 129<<16, } -#define CURSOR_BOTTOMRIGHT { 304<<16, 186<<16, } - -static MenuVerify_t M_SAVECLEANVERIFY = { CURSOR_CENTER_3LINE, MENU_SAVESETUP, MA_None, }; -static MenuVerify_t M_QUIT = { CURSOR_CENTER_2LINE, MENU_CLOSE, MA_None, }; -static MenuVerify_t M_QUITTOTITLE = { CURSOR_CENTER_2LINE, MENU_CLOSE, MA_None, }; -static MenuVerify_t M_LOADVERIFY = { CURSOR_CENTER_3LINE, MENU_CLOSE, MA_None, }; -static MenuVerify_t M_LOADDELVERIFY = { CURSOR_CENTER_3LINE, MENU_LOAD, MA_None, }; -static MenuVerify_t M_NEWVERIFY = { CURSOR_CENTER_2LINE, MENU_EPISODE, MA_Advance, }; -static MenuVerify_t M_SAVEVERIFY = { CURSOR_CENTER_2LINE, MENU_SAVE, MA_None, }; -static MenuVerify_t M_SAVEDELVERIFY = { CURSOR_CENTER_3LINE, MENU_SAVE, MA_None, }; -static MenuVerify_t M_RESETPLAYER = { CURSOR_CENTER_3LINE, MENU_CLOSE, MA_None, }; - -static MenuMessage_t M_NETWAITMASTER = { CURSOR_BOTTOMRIGHT, MENU_NULL, MA_None, }; -static MenuMessage_t M_NETWAITVOTES = { CURSOR_BOTTOMRIGHT, MENU_NULL, MA_None, }; -static MenuMessage_t M_BUYDUKE = { CURSOR_BOTTOMRIGHT, MENU_EPISODE, MA_Return, }; - -static MenuTextForm_t M_ADULTPASSWORD = { NULL, "Enter Password:", MAXPWLOCKOUT, MTF_Password }; -static MenuTextForm_t M_CHEATENTRY = { NULL, "Enter Cheat Code:", MAXCHEATLEN, 0 }; -static MenuTextForm_t M_CHEAT_WARP = { NULL, "Enter Warp #:", 3, 0 }; -static MenuTextForm_t M_CHEAT_SKILL = { NULL, "Enter Skill #:", 1, 0 }; - -//#define MAKE_MENUFILESELECT(a, b, c) { a, { &MMF_FileSelectLeft, &MMF_FileSelectRight }, { &MF_Minifont, &MF_Minifont }, b, c, { NULL, NULL }, { 0, 0 }, { 3<<16, 3<<16 }, FNLIST_INITIALIZER, 0 } - -//static MenuFileSelect_t M_USERMAP = MAKE_MENUFILESELECT( "Select A User Map", "*.map", boardfilename ); - -// MUST be in ascending order of MenuID enum values due to binary search -static Menu_t Menus[] = { - { &M_MAIN, MENU_MAIN, MENU_CLOSE, MA_None, Menu }, - { &M_MAIN_INGAME, MENU_MAIN_INGAME, MENU_CLOSE, MA_None, Menu }, - { &M_EPISODE, MENU_EPISODE, MENU_MAIN, MA_Return, Menu }, - //{ &M_USERMAP, MENU_USERMAP, MENU_EPISODE, MA_Return, FileSelect }, - { &M_SKILL, MENU_SKILL, MENU_EPISODE, MA_Return, Menu }, -#ifndef EDUKE32_SIMPLE_MENU - { &M_GAMESETUP, MENU_GAMESETUP, MENU_OPTIONS, MA_Return, Menu }, -#endif - { &M_OPTIONS, MENU_OPTIONS, MENU_MAIN, MA_Return, Menu }, - { &M_VIDEOSETUP, MENU_VIDEOSETUP, MENU_DISPLAYSETUP, MA_Return, Menu }, - { &M_KEYBOARDSETUP, MENU_KEYBOARDSETUP, MENU_CONTROLS, MA_Return, Menu }, - { &M_MOUSESETUP, MENU_MOUSESETUP, MENU_CONTROLS, MA_Return, Menu }, - { &M_JOYSTICKSETUP, MENU_JOYSTICKSETUP, MENU_CONTROLS, MA_Return, Menu }, - { &M_JOYSTICKBTNS, MENU_JOYSTICKBTNS, MENU_JOYSTICKSETUP, MA_Return, Menu }, - { &M_JOYSTICKAXES, MENU_JOYSTICKAXES, MENU_JOYSTICKSETUP, MA_Return, Menu }, - { &M_KEYBOARDKEYS, MENU_KEYBOARDKEYS, MENU_KEYBOARDSETUP, MA_Return, Menu }, - { &M_MOUSEADVANCED, MENU_MOUSEADVANCED, MENU_MOUSESETUP, MA_Return, Menu }, - { &M_JOYSTICKAXIS, MENU_JOYSTICKAXIS, MENU_JOYSTICKAXES, MA_Return, Menu }, -#ifdef EDUKE32_ANDROID_MENU - { &M_TOUCHSETUP, MENU_TOUCHSETUP, MENU_OPTIONS, MA_Return, Menu }, - { &M_TOUCHSENS, MENU_TOUCHSENS, MENU_TOUCHSETUP, MA_Return, Menu }, - { &M_TOUCHBUTTONS, MENU_TOUCHBUTTONS, MENU_TOUCHSETUP, MA_Return, Panel }, -#endif - { &M_CONTROLS, MENU_CONTROLS, MENU_OPTIONS, MA_Return, Menu }, -#ifdef USE_OPENGL - { &M_RENDERERSETUP_POLYMOST, MENU_POLYMOST, MENU_DISPLAYSETUP, MA_Return, Menu }, -#endif - { &M_COLCORR, MENU_COLCORR, MENU_DISPLAYSETUP, MA_Return, Menu }, - { &M_COLCORR, MENU_COLCORR_INGAME, MENU_CLOSE, MA_Return, Menu }, - { &M_SCREENSETUP, MENU_SCREENSETUP, MENU_DISPLAYSETUP, MA_Return, Menu }, - { &M_DISPLAYSETUP, MENU_DISPLAYSETUP, MENU_OPTIONS, MA_Return, Menu }, -#ifdef POLYMER - { &M_RENDERERSETUP_POLYMER, MENU_POLYMER, MENU_DISPLAYSETUP, MA_Return, Menu }, -#endif - { &M_LOAD, MENU_LOAD, MENU_MAIN, MA_Return, Menu }, - { &M_SAVE, MENU_SAVE, MENU_MAIN, MA_Return, Menu }, - { &M_STORY, MENU_STORY, MENU_MAIN, MA_Return, Panel }, - { &M_F1HELP, MENU_F1HELP, MENU_MAIN, MA_Return, Panel }, - { &M_F1HELP2, MENU_F1HELP2, MENU_MAIN, MA_Return, Panel }, - { &M_QUIT, MENU_QUIT, MENU_PREVIOUS, MA_Return, Verify }, - { &M_QUITTOTITLE, MENU_QUITTOTITLE, MENU_PREVIOUS, MA_Return, Verify }, - { &M_QUIT, MENU_QUIT_INGAME, MENU_CLOSE, MA_None, Verify }, - { &M_NETHOST, MENU_NETSETUP, MENU_MAIN, MA_Return, Menu }, - { &M_NETWAITMASTER, MENU_NETWAITMASTER, MENU_MAIN, MA_Return, Message }, - { &M_NETWAITVOTES, MENU_NETWAITVOTES, MENU_MAIN, MA_Return, Message }, - { &M_SOUND, MENU_SOUND, MENU_OPTIONS, MA_Return, Menu }, - { &M_SOUND, MENU_SOUND_INGAME, MENU_CLOSE, MA_Return, Menu }, - { &M_ADVSOUND, MENU_ADVSOUND, MENU_SOUND, MA_Return, Menu }, - { &M_CDPLAYER, MENU_CDPLAYER, MENU_SOUND, MA_Return, CdPlayer }, - { &M_SAVESETUP, MENU_SAVESETUP, MENU_OPTIONS, MA_Return, Menu }, - { &M_SAVECLEANVERIFY, MENU_SAVECLEANVERIFY, MENU_SAVESETUP, MA_None, Verify }, -#ifdef EDUKE32_SIMPLE_MENU - { &M_CHEATS, MENU_CHEATS, MENU_OPTIONS, MA_Return, Menu }, -#else - { &M_CHEATS, MENU_CHEATS, MENU_GAMESETUP, MA_Return, Menu }, -#endif - { &M_CHEATENTRY, MENU_CHEATENTRY, MENU_CHEATS, MA_None, TextForm }, - { &M_CHEAT_WARP, MENU_CHEAT_WARP, MENU_CHEATS, MA_None, TextForm }, - { &M_CHEAT_SKILL, MENU_CHEAT_SKILL, MENU_CHEATS, MA_None, TextForm }, - { &M_CREDITS, MENU_CREDITS, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS2, MENU_CREDITS2, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS3, MENU_CREDITS3, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS4, MENU_CREDITS4, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS5, MENU_CREDITS5, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS6, MENU_CREDITS6, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS7, MENU_CREDITS7, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS8, MENU_CREDITS8, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS9, MENU_CREDITS9, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS10, MENU_CREDITS10, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS11, MENU_CREDITS11, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS12, MENU_CREDITS12, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS13, MENU_CREDITS13, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS14, MENU_CREDITS14, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS15, MENU_CREDITS15, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS16, MENU_CREDITS16, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS17, MENU_CREDITS17, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS18, MENU_CREDITS18, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS19, MENU_CREDITS19, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS20, MENU_CREDITS20, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS21, MENU_CREDITS21, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS22, MENU_CREDITS22, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS23, MENU_CREDITS23, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS24, MENU_CREDITS24, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS25, MENU_CREDITS25, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS26, MENU_CREDITS26, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS27, MENU_CREDITS27, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS28, MENU_CREDITS28, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS29, MENU_CREDITS29, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS30, MENU_CREDITS30, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS31, MENU_CREDITS31, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS32, MENU_CREDITS32, MENU_MAIN, MA_Return, Panel }, - { &M_CREDITS33, MENU_CREDITS33, MENU_MAIN, MA_Return, Panel }, - { &M_LOADVERIFY, MENU_LOADVERIFY, MENU_LOAD, MA_None, Verify }, - { &M_LOADDELVERIFY, MENU_LOADDELVERIFY, MENU_LOAD, MA_None, Verify }, - { &M_NEWVERIFY, MENU_NEWVERIFY, MENU_PREVIOUS, MA_Return, Verify }, - { &M_SAVEVERIFY, MENU_SAVEVERIFY, MENU_SAVE, MA_None, Verify }, - { &M_SAVEDELVERIFY, MENU_SAVEDELVERIFY, MENU_SAVE, MA_None, Verify }, - { &M_ADULTPASSWORD, MENU_ADULTPASSWORD, MENU_GAMESETUP, MA_None, TextForm }, - { &M_RESETPLAYER, MENU_RESETPLAYER, MENU_CLOSE, MA_None, Verify }, - { &M_BUYDUKE, MENU_BUYDUKE, MENU_EPISODE, MA_Return, Message }, - { &M_NETWORK, MENU_NETWORK, MENU_MAIN, MA_Return, Menu }, - { &M_PLAYER, MENU_PLAYER, MENU_OPTIONS, MA_Return, Menu }, - { &M_MACROS, MENU_MACROS, MENU_PLAYER, MA_Return, Menu }, - { &M_NETHOST, MENU_NETHOST, MENU_NETWORK, MA_Return, Menu }, - { &M_NETOPTIONS, MENU_NETOPTIONS, MENU_NETWORK, MA_Return, Menu }, - //{ &M_USERMAP, MENU_NETUSERMAP, MENU_NETOPTIONS, MA_Return, FileSelect }, - { &M_NETJOIN, MENU_NETJOIN, MENU_NETWORK, MA_Return, Menu }, -}; - -static CONSTEXPR const uint16_t numMenus = ARRAY_SIZE(Menus); - -Menu_t *m_currentMenu = &Menus[0]; -static Menu_t *m_previousMenu = &Menus[0]; -static Menu_t * m_parentMenu; - -MenuID_t g_currentMenu; -static MenuID_t g_previousMenu; - -#define MenuMenu_ChangeEntryList(m, el)\ - do {\ - m.entrylist = el;\ - m.numEntries = ARRAY_SIZE(el);\ - } while (0) - -static void MenuEntry_DisableOnCondition(MenuEntry_t * const entry, const int32_t condition) -{ - if (condition) - entry->flags |= MEF_Disabled; - else - entry->flags &= ~MEF_Disabled; -} -static void MenuEntry_LookDisabledOnCondition(MenuEntry_t * const entry, const int32_t condition) -{ - if (condition) - entry->flags |= MEF_LookDisabled; - else - entry->flags &= ~MEF_LookDisabled; -} -static void MenuEntry_HideOnCondition(MenuEntry_t * const entry, const int32_t condition) -{ - if (condition) - entry->flags |= MEF_Hidden; - else - entry->flags &= ~MEF_Hidden; -} - -static int32_t M_RunMenu_Menu(Menu_t *cm, MenuMenu_t *menu, MenuEntry_t *currentry, int32_t state, vec2_t origin, bool actually_draw = true); -static void Menu_EntryFocus(/*MenuEntry_t *entry*/); - -static MenuEntry_t *Menu_AdjustForCurrentEntryAssignment(MenuMenu_t *menu) -{ - MenuEntry_t *currentry = menu->entrylist[menu->currentEntry]; - - Menu_EntryFocus(/*currentry*/); - - if (currentry->ybottom - menu->scrollPos > klabs(menu->format->bottomcutoff)) - menu->scrollPos = currentry->ybottom - klabs(menu->format->bottomcutoff); - else if (currentry->ytop - menu->scrollPos < menu->format->pos.y) - menu->scrollPos = currentry->ytop - menu->format->pos.y; - - return currentry; -} - -static MenuEntry_t *Menu_AdjustForCurrentEntryAssignmentBlind(MenuMenu_t *menu) -{ - M_RunMenu_Menu(nullptr, menu, nullptr, 0, { 0, 0 }, false); - return Menu_AdjustForCurrentEntryAssignment(menu); -} - -static int32_t SELECTDIR_z = 65536; - -/* -This function prepares data after ART and CON have been processed. -It also initializes some data in loops rather than statically at compile time. -*/ -void Menu_Init(void) -{ - int32_t i, j, k; - - // prepare menu fonts - // check if tilenum is -1 in case it was set in EVENT_SETDEFAULTS - if ((unsigned)MF_Redfont.tilenum >= MAXTILES) MF_Redfont.tilenum = BIGALPHANUM; - if ((unsigned)MF_Bluefont.tilenum >= MAXTILES) MF_Bluefont.tilenum = STARTALPHANUM; - if ((unsigned)MF_Minifont.tilenum >= MAXTILES) MF_Minifont.tilenum = MINIFONT; - MF_Redfont.emptychar.y = tilesiz[MF_Redfont.tilenum].y<<16; - MF_Bluefont.emptychar.y = tilesiz[MF_Bluefont.tilenum].y<<16; - MF_Minifont.emptychar.y = tilesiz[MF_Minifont.tilenum].y<<16; - if (!minitext_lowercase) - MF_Minifont.textflags |= TEXT_UPPERCASE; - - // prepare gamefuncs and keys - MEOSN_Gamefuncs[0] = MenuGameFuncNone; - MEOSV_Gamefuncs[0] = -1; - k = 1; - for (i = 0; i < NUMGAMEFUNCTIONS; ++i) - { - MenuGameFuncs[i] = buttonMap.GetButtonAlias(i); - MenuGameFuncs[i].Substitute('_', ' '); - } - if (RR) - { - MenuGameFuncs[gamefunc_Holo_Duke] = "Beer"; - MenuGameFuncs[gamefunc_Jetpack] = "CowPie"; - MenuGameFuncs[gamefunc_NightVision] = "Yeehaa"; - MenuGameFuncs[gamefunc_MedKit] = "Whiskey"; - MenuGameFuncs[gamefunc_Steroids] = "Moonshine"; - MenuGameFuncs[gamefunc_Quick_Kick] = "Pee"; - } - for (i = 0; i < NUMGAMEFUNCTIONS; ++i) - { - if (MenuGameFuncs[i][0] != '\0') - { - MEOSN_Gamefuncs[k] = MenuGameFuncs[i]; - MEOSV_Gamefuncs[k] = i; - ++k; - } - } - - MEOS_Gamefuncs.numOptions = k; - - for (i = 0; i < NUMKEYS; ++i) - MEOSN_Keys[i] = KB_ScanCodeToString(i); - MEOSN_Keys[NUMKEYS-1] = MenuKeyNone; - - - // prepare episodes - k = 0; - for (i = 0; i < g_volumeCnt; ++i) - { - if (g_volumeNames[i][0]) - { - if (!(g_volumeFlags[i] & EF_HIDEFROMSP)) - { - MEL_EPISODE[i] = &ME_EPISODE[i]; - ME_EPISODE[i] = ME_EPISODE_TEMPLATE; - ME_EPISODE[i].name = g_volumeNames[i]; - } - - // if (!(EpisodeFlags[i] & EF_HIDEFROMMP)) - { - MEOSN_NetEpisodes[k] = g_volumeNames[i]; - MEOSV_NetEpisodes[k] = i; - - k++; - } - } - - // prepare levels - MEOS_NETOPTIONS_LEVEL[i] = MEOS_NETOPTIONS_LEVEL_TEMPLATE; - for (j = 0; j < MAXLEVELS; ++j) - { - MEOSN_NetLevels[i][j] = g_mapInfo[MAXLEVELS*i+j].name; - if (g_mapInfo[i*MAXLEVELS+j].filename != NULL) - MEOS_NETOPTIONS_LEVEL[i].numOptions = j+1; - } - MEOS_NETOPTIONS_LEVEL[i].optionNames = MEOSN_NetLevels[i]; - } - M_EPISODE.numEntries = g_volumeCnt+2; -#ifndef EDUKE32_SIMPLE_MENU - MEL_EPISODE[g_volumeCnt] = &ME_Space4_Redfont; - MEL_EPISODE[g_volumeCnt+1] = &ME_EPISODE_USERMAP; - MEOSN_NetEpisodes[k] = MenuUserMap; - MEOSV_NetEpisodes[k] = MAXVOLUMES; -#else - M_EPISODE.numEntries = g_volumeCnt; - k--; -#endif - MEOS_NETOPTIONS_EPISODE.numOptions = k + 1; - NetEpisode = MEOSV_NetEpisodes[0]; - MMF_Top_Episode.pos.y = (58 + (3-k)*6)<<16; - if (g_skillCnt == 0) - MEO_EPISODE.linkID = MENU_NULL; - M_EPISODE.currentEntry = ud.default_volume; - - // prepare skills - k = -1; - for (i = 0; i < g_skillCnt && g_skillNames[i][0]; ++i) - { - MEL_SKILL[i] = &ME_SKILL[i]; - ME_SKILL[i] = ME_SKILL_TEMPLATE; - ME_SKILL[i].name = g_skillNames[i]; - - MEOSN_NetSkills[i] = g_skillNames[i]; - - k = i; - } - ++k; - M_SKILL.numEntries = g_skillCnt; // k; - MEOS_NETOPTIONS_MONSTERS.numOptions = g_skillCnt + 1; // k+1; - MEOSN_NetSkills[g_skillCnt] = MenuSkillNone; - MMF_Top_Skill.pos.y = (58 + (4-g_skillCnt)*6)<<16; - M_SKILL.currentEntry = ud.default_skill; - Menu_AdjustForCurrentEntryAssignmentBlind(&M_SKILL); - - // prepare multiplayer gametypes - k = -1; - for (i = 0; i < MAXGAMETYPES; ++i) - if (g_gametypeNames[i][0]) - { - MEOSN_NetGametypes[i] = g_gametypeNames[i]; - k = i; - } - ++k; - MEOS_NETOPTIONS_GAMETYPE.numOptions = k; - - // prepare cheats - for (i = 0; i < NUMCHEATFUNCS; ++i) - MEL_CHEATS[i+1] = &ME_CheatCodes[i]; - - // prepare text chat macros - for (i = 0; i < MAXRIDECULE; ++i) - { - MEL_MACROS[i] = &ME_MACROS[i]; - ME_MACROS[i] = ME_MACROS_TEMPLATE; - ME_MACROS[i].entry = &MEO_MACROS[i]; - MEO_MACROS[i] = MEO_MACROS_TEMPLATE; - - MEO_MACROS[i].variable = sink;// ud.ridecule[i]; temporarily disabled - } - - // prepare input - for (i = 0; i < NUMGAMEFUNCTIONS; ++i) - { - if (MenuGameFuncs[i][0] == '\0') - { - MEL_KEYBOARDSETUPFUNCS[i] = NULL; - continue; - } - - MEL_KEYBOARDSETUPFUNCS[i] = &ME_KEYBOARDSETUPFUNCS[i]; - ME_KEYBOARDSETUPFUNCS[i] = ME_KEYBOARDSETUPFUNCS_TEMPLATE; - ME_KEYBOARDSETUPFUNCS[i].name = MenuGameFuncs[i]; - ME_KEYBOARDSETUPFUNCS[i].entry = &MEO_KEYBOARDSETUPFUNCS[i]; - MEO_KEYBOARDSETUPFUNCS[i] = MEO_KEYBOARDSETUPFUNCS_TEMPLATE; - } - M_KEYBOARDKEYS.numEntries = NUMGAMEFUNCTIONS; - for (i = 0; i < 2*joystick.numButtons + 8*joystick.numHats; ++i) - { - if (i < 2*joystick.numButtons) - { - if (i & 1) - Bsnprintf(MenuJoystickNames[i], MAXJOYBUTTONSTRINGLENGTH, "Double %s", joyGetName(1, i>>1)); - else - Bstrncpy(MenuJoystickNames[i], joyGetName(1, i>>1), MAXJOYBUTTONSTRINGLENGTH); - } - else - { - Bsnprintf(MenuJoystickNames[i], MAXJOYBUTTONSTRINGLENGTH, (i & 1) ? "Double Hat %d %s" : "Hat %d %s", ((i - 2*joystick.numButtons)>>3), MenuJoystickHatDirections[((i - 2*joystick.numButtons)>>1) % 4]); - } - } - for (i = 0; i < joystick.numAxes; ++i) - { - ME_JOYSTICKAXES[i] = ME_JOYSTICKAXES_TEMPLATE; - Bstrncpy(MenuJoystickAxes[i], joyGetName(0, i), MAXJOYBUTTONSTRINGLENGTH); - ME_JOYSTICKAXES[i].name = MenuJoystickAxes[i]; - MEL_JOYSTICKAXES[i] = &ME_JOYSTICKAXES[i]; - } - M_JOYSTICKAXES.numEntries = joystick.numAxes; - - // prepare video setup - for (i = 0; i < validmodecnt; ++i) - { - for (j = 0; j < MEOS_VIDEOSETUP_RESOLUTION.numOptions; ++j) - { - if (validmode[i].xdim == resolution[j].xdim && validmode[i].ydim == resolution[j].ydim) - { - resolution[j].flags |= validmode[i].fs ? RES_FS : RES_WIN; - Bsnprintf(resolution[j].name, MAXRESOLUTIONSTRINGLENGTH, "%d x %d%s", resolution[j].xdim, resolution[j].ydim, (resolution[j].flags & RES_FS) ? "" : "Win"); - MEOSN_VIDEOSETUP_RESOLUTION[j] = resolution[j].name; - if (validmode[i].bpp > resolution[j].bppmax) - resolution[j].bppmax = validmode[i].bpp; - break; - } - } - - if (j == MEOS_VIDEOSETUP_RESOLUTION.numOptions) // no match found - { - resolution[j].xdim = validmode[i].xdim; - resolution[j].ydim = validmode[i].ydim; - resolution[j].bppmax = validmode[i].bpp; - resolution[j].flags = validmode[i].fs ? RES_FS : RES_WIN; - Bsnprintf(resolution[j].name, MAXRESOLUTIONSTRINGLENGTH, "%d x %d%s", resolution[j].xdim, resolution[j].ydim, (resolution[j].flags & RES_FS) ? "" : "Win"); - MEOSN_VIDEOSETUP_RESOLUTION[j] = resolution[j].name; - ++MEOS_VIDEOSETUP_RESOLUTION.numOptions; - } - } - #if 0 - // prepare sound setup - if (WW2GI) - ME_SOUND_DUKETALK.name = "GI talk:"; - else if (NAM) - ME_SOUND_DUKETALK.name = "Grunt talk:"; - if (IONMAIDEN) - { - MF_Redfont.between.x = 2<<16; - MF_Redfont.cursorScale = 32768; - MF_Redfont.zoom = 16384; - MF_Bluefont.zoom = 16384; - - // hack; should swap out pointers - MF_Minifont = MF_Bluefont; - - MMF_Top_Main.pos.x = 40<<16; - MMF_Top_Main.pos.y = 130<<16; - MMF_Top_Main.bottomcutoff = 190<<16; - M_OPTIONS.format = &MMF_Top_Main; - - MEF_MainMenu.width = MEF_OptionsMenu.width = -(160<<16); - MEF_MainMenu.marginBottom = 7<<16; - - M_OPTIONS.title = NoTitle; - - SELECTDIR_z = 16384; - } -#endif - - if (RR) - { - MF_Redfont.zoom = 32768; - MF_Redfont.emptychar.x <<= 1; - MF_Redfont.cursorScale = 13107; - MF_Redfont.cursorScale2 = 6553; - //MF_Redfont.emptychar.y <<= 1; - MF_Bluefont.zoom = 32768; - MF_Bluefont.emptychar.x <<= 1; - MF_Bluefont.cursorScale = 6553; - MF_Bluefont.cursorScale2 = 6553; - //MF_Bluefont.emptychar.y <<= 1; - MF_Minifont.zoom = 32768; - MF_Minifont.emptychar.x <<= 1; - MF_Minifont.cursorScale = 6553; - MF_Minifont.cursorScale2 = 6553; - //MF_Minifont.emptychar.y <<= 1; - ME_SOUND_DUKETALK.name = "Leonard Talk:"; - } - else if (NAPALM) - { - ME_SOUND_DUKETALK.name = "NAPALM Talk:"; - } - else if (NAM) - { - ME_SOUND_DUKETALK.name = "NAM Talk:"; - } - - // prepare shareware - if (VOLUMEONE) - { - // blue out episodes beyond the first - for (i = 1; i < g_volumeCnt; ++i) - { - if (MEL_EPISODE[i]) - { - ME_EPISODE[i].entry = &MEO_EPISODE_SHAREWARE; - ME_EPISODE[i].flags |= MEF_LookDisabled; - } - } - M_EPISODE.numEntries = g_volumeCnt; // remove User Map (and spacer) - MEOS_NETOPTIONS_EPISODE.numOptions = 1; - MenuEntry_DisableOnCondition(&ME_NETOPTIONS_EPISODE, 1); - } - - if (RR) - { - MEL_SOUND[0] = &ME_SOUND_CDPLAYER; - MEL_SOUND[1] = &ME_SOUND; - M_CREDITS.title = M_CREDITS2.title = M_CREDITS3.title = s_Credits; - M_CREDITS3.nextID = MENU_CREDITS4; - M_STORY.previousID = M_STORY.nextID = MENU_F1HELP; - if (RRRA) - { - M_CREDITS31.previousID = MENU_CREDITS30; - M_STORY.previousID = MENU_F1HELP2; - M_F1HELP.nextID = MENU_F1HELP2; - } - else - { - M_CREDITS31.previousID = MENU_CREDITS23; - M_CREDITS23.nextID = MENU_CREDITS31; - } - } - // prepare pre-Atomic - else if (!VOLUMEALL || !PLUTOPAK) - { - // prepare credits - M_CREDITS.title = M_CREDITS2.title = M_CREDITS3.title = s_Credits; - } -} - -static void Menu_Run(Menu_t *cm, vec2_t origin); - - -static void Menu_BlackRectangle(int32_t x, int32_t y, int32_t width, int32_t height, int32_t orientation); - -/* -At present, no true difference is planned between Menu_Pre() and Menu_PreDraw(). -They are separate for purposes of organization. -*/ - -static void Menu_Pre(MenuID_t cm) -{ - int32_t i; - DukePlayer_t *ps = g_player[myconnectindex].ps; - - switch (cm) - { - case MENU_MAIN_INGAME: - MenuEntry_DisableOnCondition(&ME_MAIN_LOADGAME, (RRRA && ud.player_skill == 4) || (RR && !RRRA && ud.player_skill == 5)); - MenuEntry_DisableOnCondition(&ME_MAIN_SAVEGAME, ud.recstat == 2 || (RRRA && ud.player_skill == 4) || (RR && !RRRA && ud.player_skill == 5)); - MenuEntry_DisableOnCondition(&ME_MAIN_QUITTOTITLE, g_netServer || numplayers > 1); - fallthrough__; - case MENU_MAIN: - if ((g_netServer || ud.multimode > 1) && ud.recstat != 2) - { - ME_MAIN_NEWGAME.entry = &MEO_MAIN_NEWGAME_NETWORK; - ME_MAIN_NEWGAME_INGAME.entry = &MEO_MAIN_NEWGAME_NETWORK; - } - else - { - ME_MAIN_NEWGAME.entry = &MEO_MAIN_NEWGAME; - ME_MAIN_NEWGAME_INGAME.entry = &MEO_MAIN_NEWGAME_INGAME; - } - break; - - case MENU_GAMESETUP: - MEO_GAMESETUP_DEMOREC.options = (ps->gm&MODE_GAME) ? &MEOS_DemoRec : &MEOS_OffOn; - MenuEntry_DisableOnCondition(&ME_GAMESETUP_DEMOREC, (ps->gm&MODE_GAME) && m_recstat != 1); - break; - -#ifdef USE_OPENGL - case MENU_DISPLAYSETUP: - if (videoGetRenderMode() == REND_CLASSIC) - MenuMenu_ChangeEntryList(M_DISPLAYSETUP, MEL_DISPLAYSETUP); -#ifdef POLYMER - else if (videoGetRenderMode() == REND_POLYMER) - MenuMenu_ChangeEntryList(M_DISPLAYSETUP, MEL_DISPLAYSETUP_GL_POLYMER); -#endif - else - MenuMenu_ChangeEntryList(M_DISPLAYSETUP, MEL_DISPLAYSETUP_GL); - - MEO_SCREENSETUP_SCREENSIZE.steps = !(ud.statusbarflags & STATUSBAR_NONONE) + - !(ud.statusbarflags & STATUSBAR_NOMODERN) + - !(ud.statusbarflags & STATUSBAR_NOMINI) + - !(ud.statusbarflags & STATUSBAR_NOOVERLAY) + - !(ud.statusbarflags & STATUSBAR_NOFULL) + - !(ud.statusbarflags & STATUSBAR_NOSHRINK) * 14; - MEO_SCREENSETUP_SCREENSIZE.max = MEO_SCREENSETUP_SCREENSIZE.steps - 1; - MenuEntry_DisableOnCondition(&ME_SCREENSETUP_SCREENSIZE, (MEO_SCREENSETUP_SCREENSIZE.steps < 2)); - - if (videoGetRenderMode() != REND_CLASSIC) - { - //POGOTODO: allow setting anisotropy again while hw_useindexedcolortextures is set when support is added down the line - // don't allow setting anisotropy or changing palette emulation while in POLYMOST and hw_useindexedcolortextures is enabled - MenuEntry_DisableOnCondition(&ME_DISPLAYSETUP_ANISOTROPY, videoGetRenderMode() == REND_POLYMOST && hw_useindexedcolortextures); -#ifdef EDUKE32_SIMPLE_MENU - MenuEntry_DisableOnCondition(&ME_DISPLAYSETUP_PALETTEEMULATION, videoGetRenderMode() == REND_POLYMOST && hw_useindexedcolortextures); -#endif - - for (i = (int32_t) ARRAY_SIZE(MEOSV_DISPLAYSETUP_ANISOTROPY) - 1; i >= 0; --i) - { - if (MEOSV_DISPLAYSETUP_ANISOTROPY[i] <= GLInterface.glinfo.maxanisotropy) - { - MEOS_DISPLAYSETUP_ANISOTROPY.numOptions = i + 1; - break; - } - } - } - break; - - case MENU_POLYMER: - case MENU_POLYMOST: - MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_PRECACHE, !hw_hightile); -# ifdef USE_GLEXT - MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_DETAILTEX, !hw_hightile); - MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_GLOWTEX, !hw_hightile); -# endif - break; -#endif - - case MENU_VIDEOSETUP: - { - const int32_t nr = newresolution; - - // don't allow setting fullscreen mode if it's not supported by the resolution - MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_FULLSCREEN, !(resolution[nr].flags & RES_FS)); - - MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_APPLY, - (xres == resolution[nr].xdim && yres == resolution[nr].ydim && - videoGetRenderMode() == newrendermode && fullscreen == newfullscreen - && vid_vsync == newvsync - ) - || (newrendermode != REND_CLASSIC && resolution[nr].bppmax <= 8)); - - break; - } - - case MENU_SOUND: - case MENU_SOUND_INGAME: - case MENU_ADVSOUND: - MenuEntry_DisableOnCondition(&ME_SOUND_VOLUME_FX, !snd_enabled); - MenuEntry_DisableOnCondition(&ME_SOUND_VOLUME_MUSIC, !mus_enabled); - MenuEntry_DisableOnCondition(&ME_SOUND_DUKETALK, !snd_enabled); - MenuEntry_DisableOnCondition(&ME_SOUND_SAMPLINGRATE, !snd_enabled && !mus_enabled); -#ifndef EDUKE32_SIMPLE_MENU - MenuEntry_DisableOnCondition(&ME_SOUND_NUMVOICES, !snd_enabled); -#endif - MenuEntry_DisableOnCondition(&ME_SOUND_RESTART, soundrate == snd_mixrate && - soundvoices == snd_numvoices); - break; - - case MENU_SAVESETUP: - MenuEntry_DisableOnCondition(&ME_SAVESETUP_MAXAUTOSAVES, !cl_autosavedeletion); - break; - -#ifndef EDUKE32_SIMPLE_MENU - case MENU_MOUSESETUP: - MenuEntry_DisableOnCondition(&ME_MOUSESETUP_MOUSEAIMING, in_aimmode); - break; -#endif - case MENU_NETOPTIONS: - if (MEOSV_NetEpisodes[MEO_NETOPTIONS_EPISODE.currentOption] == MAXVOLUMES) - MEL_NETOPTIONS[2] = &ME_NETOPTIONS_USERMAP; - else - { - MEL_NETOPTIONS[2] = &ME_NETOPTIONS_LEVEL; - MEO_NETOPTIONS_LEVEL.options = &MEOS_NETOPTIONS_LEVEL[MEOSV_NetEpisodes[MEO_NETOPTIONS_EPISODE.currentOption]]; - } - if (!(g_gametypeFlags[m_coop] & GAMETYPE_MARKEROPTION)) - { - ME_NETOPTIONS_MARKERS.type = Dummy; - ME_NETOPTIONS_MARKERS.flags |= MEF_Disabled; - } - else - { - ME_NETOPTIONS_MARKERS.type = Option; - ME_NETOPTIONS_MARKERS.flags &= ~MEF_Disabled; - } - MEL_NETOPTIONS[5] = (g_gametypeFlags[m_coop] & (GAMETYPE_PLAYERSFRIENDLY|GAMETYPE_TDM)) ? &ME_NETOPTIONS_FRFIRE : &ME_NETOPTIONS_MAPEXITS; - break; - - case MENU_OPTIONS: - MenuEntry_DisableOnCondition(&ME_OPTIONS_PLAYERSETUP, ud.recstat == 1); - MenuEntry_HideOnCondition(&ME_OPTIONS_JOYSTICKSETUP, !in_joystick || CONTROL_JoyPresent == 0); - break; - - case MENU_COLCORR: - case MENU_COLCORR_INGAME: - break; - - case MENU_CHEATS: - case MENU_CHEATENTRY: - case MENU_CHEAT_WARP: - case MENU_CHEAT_SKILL: - { - const int32_t menucheatsdisabled = numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME); - - // refresh display names of quote cheats - ME_CheatCodes[CHEATFUNC_QUOTEBETA].name = apStrings[QUOTE_CHEAT_BETA]; - ME_CheatCodes[CHEATFUNC_QUOTETODD].name = apStrings[QUOTE_CHEAT_TODD]; - ME_CheatCodes[CHEATFUNC_QUOTEALLEN].name = apStrings[QUOTE_CHEAT_ALLEN]; - - for (i = 0; i < NUMCHEATFUNCS; i++) - { - uint32_t cheatmask = cl_cheatmask & (1<>11),0,2+8); - } - break; - - case MENU_CDPLAYER: - rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y+(100<<16),32768L,0,CDPLAYER,16,0,10); - break; - - case MENU_PLAYER: - if (RR) - rotatesprite_fs(origin.x + (260<<16), origin.y + ((24+(tilesiz[APLAYER].y>>2))<<16), 24576L,0,3845+36-((((8-((int32_t) totalclock>>4)))&7)*5),0,entry == &ME_PLAYER_TEAM ? G_GetTeamPalette(playerteam) : playercolor,10); - else - rotatesprite_fs(origin.x + (260<<16), origin.y + ((24+(tilesiz[APLAYER].y>>1))<<16), 49152L,0,1441-((((4-((int32_t) totalclock>>4)))&3)*5),0,entry == &ME_PLAYER_TEAM ? G_GetTeamPalette(playerteam) : playercolor,10); - break; - - case MENU_MACROS: - mgametextcenter(origin.x, origin.y + (144<<16), "Activate in-game with Shift-F#"); - break; - - case MENU_COLCORR: - case MENU_COLCORR_INGAME: - // center panel - if (!RR) - rotatesprite_fs(origin.x + (120<<16), origin.y + (32<<16), 16384, 0, 3290, 0, 0, 2|8|16); - rotatesprite_fs(origin.x + (160<<16) - (tilesiz[BOTTOMSTATUSBAR].x<<(RR ? 12 : 13)), origin.y + (82<<16) - (tilesiz[BOTTOMSTATUSBAR].y<<14), RR ? 8192 : 16384, 0, BOTTOMSTATUSBAR, 0, 0, 2|8|16); - - // left panel - rotatesprite_fs(origin.x + (40<<16), origin.y + (32<<16), 16384, 0, RR ? RRTILE403 : BONUSSCREEN, 0, 0, 2|8|16); - - // right panel - rotatesprite_fs(origin.x + (200<<16), origin.y + (32<<16), 16384, 0, LOADSCREEN, 0, 0, 2|8|16); - break; - - case MENU_NETSETUP: - case MENU_NETHOST: - mminitext(origin.x + (90<<16), origin.y + (90<<16), "Game Type", MF_Minifont.pal_deselected); - mminitext(origin.x + (90<<16), origin.y + ((90+8)<<16), "Episode", MF_Minifont.pal_deselected); - mminitext(origin.x + (90<<16), origin.y + ((90+8+8)<<16), "Level", MF_Minifont.pal_deselected); - mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8)<<16), ME_NETOPTIONS_MONSTERS.name, MF_Minifont.pal_deselected); - if (m_coop == 0) - mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8)<<16), "Markers", MF_Minifont.pal_deselected); - else if (m_coop == 1) - mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8)<<16), "Friendly Fire", MF_Minifont.pal_deselected); - mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8+8)<<16), "User Map", MF_Minifont.pal_deselected); - - mminitext(origin.x + ((90+60)<<16), origin.y + (90<<16), g_gametypeNames[m_coop], MF_Minifont.pal_deselected_right); - - mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8)<<16), g_volumeNames[ud.m_volume_number], MF_Minifont.pal_deselected_right); - mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8)<<16), g_mapInfo[MAXLEVELS*ud.m_volume_number+m_level_number].name, MF_Minifont.pal_deselected_right); - if (ud.m_monsters_off == 0 || ud.m_player_skill > 0) - mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), g_skillNames[ud.m_player_skill], MF_Minifont.pal_deselected_right); - else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), "None", MF_Minifont.pal_deselected_right); - if (m_coop == 0) - { - if (m_marker) mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "On", MF_Minifont.pal_deselected_right); - else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "Off", MF_Minifont.pal_deselected_right); - } - else if (m_coop == 1) - { - if (m_ffire) mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "On", MF_Minifont.pal_deselected_right); - else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "Off", MF_Minifont.pal_deselected_right); - } - break; - - case MENU_MOUSEADVANCED: - break; - - case MENU_RESETPLAYER: - videoFadeToBlack(1); - Bsprintf(tempbuf, "Load last game:\n\"%s\"" -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - , g_quickload->name); - mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); - break; - - case MENU_LOAD: - { -#if 0 - for (i = 0; i <= 108; i += 12) - rotatesprite_fs(origin.x + ((160+64+91-64)<<16), origin.y + ((i+56)<<16), 65536L,0,TEXTBOX,24,0,10); -#endif - Menu_BlackRectangle(origin.x + (198<<16), origin.y + (47<<16), 102<<16, 100<<16, 1|32); - - rotatesprite_fs(origin.x + (22<<16), origin.y + (97<<16), 65536L,0,WINDOWBORDER2,24,0,10); - rotatesprite_fs(origin.x + (180<<16), origin.y + (97<<16), 65536L,1024,WINDOWBORDER2,24,0,10); - rotatesprite_fs(origin.x + (99<<16), origin.y + (50<<16), 65536L,512,WINDOWBORDER1,24,0,10); - rotatesprite_fs(origin.x + (103<<16), origin.y + (144<<16), 65536L,1024+512,WINDOWBORDER1,24,0,10); - - if (M_LOAD.currentEntry >= (int32_t)g_nummenusaves) - { - menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "Empty"); - break; - } - - menusave_t & msv = g_menusaves[M_LOAD.currentEntry]; - - if (msv.brief.isValid()) - { - rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536>>1,512,TILE_LOADSHOT,-32,0,4+10+64); - - if (msv.isOldVer) - { - menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "Previous\nVersion"); - -#ifndef EDUKE32_SIMPLE_MENU - Bsprintf(tempbuf,"Saved: %d.%d.%d.%u %d-bit", savehead.majorver, savehead.minorver, - savehead.bytever, savehead.userbytever, 8*savehead.getPtrSize()); - mgametext(origin.x + (31<<16), origin.y + (104<<16), tempbuf); - Bsprintf(tempbuf,"Our: %d.%d.%d.%u %d-bit", SV_MAJOR_VER, SV_MINOR_VER, BYTEVERSION, - ud.userbytever, (int32_t)(8*sizeof(intptr_t))); - mgametext(origin.x + ((31+16)<<16), origin.y + (114<<16), tempbuf); -#endif - - break; - } - - if (savehead.numplayers > 1) - { - Bsprintf(tempbuf, "Players: %-2d ", savehead.numplayers); - mgametextcenter(origin.x, origin.y + (156<<16), tempbuf); - } - - { - const char *name = g_mapInfo[(savehead.volnum*MAXLEVELS) + savehead.levnum].name; - Bsprintf(tempbuf, "%s / %s", name ? name : "^10unnamed^0", g_skillNames[savehead.skill-1]); - } - - mgametextcenter(origin.x, origin.y + (168<<16), tempbuf); - if (savehead.volnum == 0 && savehead.levnum == 7) - mgametextcenter(origin.x, origin.y + (180<<16), savehead.boardfn); - } - break; - } - - case MENU_SAVE: - { -#if 0 - for (i = 0; i <= 108; i += 12) - rotatesprite_fs(origin.x + ((160+64+91-64)<<16), origin.y + ((i+56)<<16), 65536L,0,TEXTBOX,24,0,10); -#endif - Menu_BlackRectangle(origin.x + (198<<16), origin.y + (47<<16), 102<<16, 100<<16, 1|32); - - rotatesprite_fs(origin.x + (22<<16), origin.y + (97<<16), 65536L,0,WINDOWBORDER2,24,0,10); - rotatesprite_fs(origin.x + (180<<16), origin.y + (97<<16), 65536L,1024,WINDOWBORDER2,24,0,10); - rotatesprite_fs(origin.x + (99<<16), origin.y + (50<<16), 65536L,512,WINDOWBORDER1,24,0,10); - rotatesprite_fs(origin.x + (103<<16), origin.y + (144<<16), 65536L,1024+512,WINDOWBORDER1,24,0,10); - - j = 0; - for (int k = 0; k < g_nummenusaves+1; ++k) - if (((MenuString_t*)M_SAVE.entrylist[k]->entry)->editfield) - j |= 1; - - if (j) - rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536L>>1,512,TILE_SAVESHOT,-32,0,4+10+64); - else if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves) - { - if (g_menusaves[M_SAVE.currentEntry-1].brief.isValid()) - { - rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536L>>1,512,TILE_LOADSHOT,-32,0,4+10+64); - - if (g_menusaves[M_SAVE.currentEntry-1].isOldVer) - { - menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "Previous\nVersion"); - -#ifndef EDUKE32_SIMPLE_MENU - Bsprintf(tempbuf,"Saved: %d.%d.%d.%u %d-bit", savehead.majorver, savehead.minorver, - savehead.bytever, savehead.userbytever, 8*savehead.getPtrSize()); - mgametext(origin.x + (31<<16), origin.y + (104<<16), tempbuf); - Bsprintf(tempbuf,"Our: %d.%d.%d.%u %d-bit", SV_MAJOR_VER, SV_MINOR_VER, BYTEVERSION, - ud.userbytever, (int32_t)(8*sizeof(intptr_t))); - mgametext(origin.x + ((31+16)<<16), origin.y + (114<<16), tempbuf); -#endif - - break; - } - } - } - else - menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "New"); - - if (ud.multimode > 1) - { - Bsprintf(tempbuf, "Players: %-2d ", ud.multimode); - mgametextcenter(origin.x, origin.y + (156<<16), tempbuf); - } - - Bsprintf(tempbuf,"%s / %s",g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]); - mgametextcenter(origin.x, origin.y + (168<<16), tempbuf); - if (ud.volume_number == 0 && ud.level_number == 7) - mgametextcenter(origin.x, origin.y + (180<<16), currentboardfilename); - break; - } - -#ifdef EDUKE32_ANDROID_MENU - case MENU_SKILL: - { - static const char *s[] = { "EASY - Few enemies, and lots of stuff.", "MEDIUM - Normal difficulty.", "HARD - For experienced players.", "EXPERTS - Lots of enemies, plus they respawn!" }; - if (M_SKILL.currentEntry < ARRAY_SSIZE(s)) - mgametextcenter(origin.x, origin.y + (168<<16), s[M_SKILL.currentEntry]); - } - break; -#endif - - case MENU_SAVECLEANVERIFY: - videoFadeToBlack(1); - - if (g_oldSaveCnt) - { - Bsprintf(tempbuf, "Delete %d obsolete saves?\nThis action cannot be undone." -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - , g_oldSaveCnt); - } - else - Bsprintf(tempbuf, "No obsolete saves found!"); - - mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); - break; - - case MENU_LOADVERIFY: - { - videoFadeToBlack(1); - menusave_t & msv = g_menusaves[M_LOAD.currentEntry]; - if (msv.isOldVer) - { - Bsprintf(tempbuf, "Start new game:\n%s / %s" -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - , g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]); - mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); - } - else - { - Bsprintf(tempbuf, "Load game:\n\"%s\"" -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - , msv.brief.name); - mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); - } - break; - } - - case MENU_SAVEVERIFY: - videoFadeToBlack(1); - mgametextcenter(origin.x, origin.y + (90<<16), "Overwrite previous saved game?" -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - ); - break; - - case MENU_LOADDELVERIFY: - case MENU_SAVEDELVERIFY: - { - videoFadeToBlack(1); - menusave_t & msv = cm == MENU_LOADDELVERIFY ? g_menusaves[M_LOAD.currentEntry] : g_menusaves[M_SAVE.currentEntry-1]; - Bsprintf(tempbuf, "Delete saved game:\n\"%s\"?" -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - , msv.brief.name); - mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); - break; - } - - case MENU_NEWVERIFY: - videoFadeToBlack(1); - mgametextcenter(origin.x, origin.y + (90<<16), "Abort this game?" -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - ); - break; - - case MENU_QUIT: - case MENU_QUIT_INGAME: - videoFadeToBlack(1); - mgametextcenter(origin.x, origin.y + (90<<16), "Are you sure you want to quit?" -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - ); - break; - - case MENU_QUITTOTITLE: - videoFadeToBlack(1); - mgametextcenter(origin.x, origin.y + (90<<16), "End game and return to title screen?" -#ifndef EDUKE32_ANDROID_MENU - "\n(Y/N)" -#endif - ); - break; - - case MENU_NETWAITMASTER: - G_DrawFrags(); - mgametextcenter(origin.x, origin.y + (50<<16), "Waiting for master\n" - "to select level"); - break; - - case MENU_NETWAITVOTES: - G_DrawFrags(); - mgametextcenter(origin.x, origin.y + (90<<16), "Waiting for votes"); - break; - - case MENU_BUYDUKE: - mgametextcenter(origin.x, origin.y + (33<<16), "You are playing the shareware\n" - "version of Duke Nukem 3D. While\n" - "this version is really cool, you\n" - "are missing over 75% of the total\n" - "game, along with other great extras\n" - "which you'll get when you order\n" - "the complete version and get\n" - "the final three episodes."); - - mgametextcenter(origin.x, origin.y + ((148+16)<<16), "Press any key or button..."); - break; - - case MENU_CREDITS: - case MENU_CREDITS2: - case MENU_CREDITS3: - case MENU_CREDITS4: - case MENU_CREDITS5: - case MENU_CREDITS6: - case MENU_CREDITS7: - case MENU_CREDITS8: - case MENU_CREDITS9: - case MENU_CREDITS10: - case MENU_CREDITS11: - case MENU_CREDITS12: - case MENU_CREDITS13: - case MENU_CREDITS14: - case MENU_CREDITS15: - case MENU_CREDITS16: - case MENU_CREDITS17: - case MENU_CREDITS18: - case MENU_CREDITS19: - case MENU_CREDITS20: - case MENU_CREDITS21: - case MENU_CREDITS22: - case MENU_CREDITS23: - case MENU_CREDITS24: - case MENU_CREDITS25: - case MENU_CREDITS26: - case MENU_CREDITS27: - case MENU_CREDITS28: - case MENU_CREDITS29: - case MENU_CREDITS30: - if (RR) - { - if (RRRA) - { - switch (cm) - { - case MENU_CREDITS: - mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL CONCEPT, DESIGN AND DIRECTION\n\n" - "DREW MARKHAM"); - break; - - case MENU_CREDITS2: - mgametextcenter(origin.x, origin.y + (80<<16), "ART DIRECTION AND ADDITIONAL DESIGN\n\n" - "CORKY LEHMKUHL"); - break; - - case MENU_CREDITS3: - mgametextcenter(origin.x, origin.y + (80<<16), "PRODUCED BY\n\n" - "GREG GOODRICH"); - break; - - case MENU_CREDITS4: - mgametextcenter(origin.x, origin.y + (80<<16), "GAME PROGRAMMING\n\n" - "JOSEPH AURILI"); - break; - - case MENU_CREDITS5: - mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL GAME PROGRAMMING\n\n" - "RAFAEL PAIZ"); - break; - - case MENU_CREDITS6: - mgametextcenter(origin.x, origin.y + (80<<16), "LEVEL DESIGN\n\n" - "RHETT BALDWIN & AARON BARBER"); - break; - - case MENU_CREDITS7: - mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL ART DIRECTION AND SUPPORT\n\n" - "MAXX KAUFMAN & CLAIRE PRADERIE-MARKHAM"); - break; - - case MENU_CREDITS8: - mgametextcenter(origin.x, origin.y + (80<<16), "COMPUTER GRAPHICS SUPERVISOR &\n" - "CHARACTER ANIMATION DIRECTION\n\n" - "BARRY DEMPSEY"); - break; - - case MENU_CREDITS9: - mgametextcenter(origin.x, origin.y + (80<<16), "SENIOR ANIMATOR & MODELER\n\n" - "JASON HOOVER"); - break; - - case MENU_CREDITS10: - mgametextcenter(origin.x, origin.y + (80<<16), "CHARACTER ANIMATION &\n" - "MOTION CAPTURE SPECIALIST\n\n" - "AMIT DORON"); - break; - - case MENU_CREDITS11: - mgametextcenter(origin.x, origin.y + (80<<16), "SOUND DESIGN &\n" - "MUSIC PRODUCTION COORDINATION\n\n" - "GARY BRADFIELD"); - break; - - case MENU_CREDITS12: - mgametextcenter(origin.x, origin.y + (80<<16), "INTRODUCTION ANIMATION\n\n" - "DOMINIQUE DROZDZ"); - break; - - case MENU_CREDITS13: - mgametextcenter(origin.x, origin.y + (80<<16), "ARTIST\n\n" - "MATTHIAS BEEGUER"); - break; - - case MENU_CREDITS14: - mgametextcenter(origin.x, origin.y + (80<<16), "ADDITIONAL ART\n\n" - "VIKTOR ANTONOV"); - break; - - case MENU_CREDITS15: - mgametextcenter(origin.x, origin.y + (80<<16), "PRODUCTION COORDINATOR\n\n" - "VICTORIA SYLVESTER"); - break; - - case MENU_CREDITS16: - mgametextcenter(origin.x, origin.y + (40<<16), "CHARACTER VOICES\n\n" - "LEONARD\n" - "BURTON GILLIAM\n\n" - "DAISY MAE\n" - "TARA CHARENDOFF\n\n" - "BUBBA, BILLY RAY, SKINNY OL' COOT,\n" - "FRANK THE BIKER, THE TURD MINION\n" - "& ALL OTHER VARIOUS RAMBLINGS...\n" - "DREW MARKHAM"); - break; - - case MENU_CREDITS17: - mgametextcenter(origin.x, origin.y + (70<<16), "SPECIAL APPEARENCE BY\n\n" - "SHERIFF LESTER T. HOBBES\n" - "MOJO NIXON\n\n" - "ALIEN VIXEN\n" - "PEGGY JO JACOBS"); - break; - - case MENU_CREDITS18: - mgametextcenter(origin.x, origin.y + (70<<16), "REDNECK RAMPAGE TITLE TRACK & CYBERSEX\n" - "WRITTEN & PERFORMED BY\n" - "MOJO NIXON\n\n" - "(c) MUFFIN'STUFFIN' MUSIC (BMI)\n" - "ADMINISTERED BY BUG."); - break; - - case MENU_CREDITS19: - mgametextcenter(origin.x, origin.y + (60<<16), "MUSIC\n\n" - "DISGRACELAND\n" - "TINY D & THE SOFA KINGS\n\n" - "BANJO AND GUITAR PICKIN\n" - "JOHN SCHLOCKER\n" - "HOWARD YEARWOOD"); - break; - - case MENU_CREDITS20: - mgametextcenter(origin.x, origin.y + (80<<16), "RECORDING ENGINEER\n" - "DAVE AHLERT\n\n" - "RECORDING ASSISTANCE\n" - "JEFF GILBERT"); - break; - - case MENU_CREDITS21: - mgametextcenter(origin.x, origin.y + (80<<16), "MOTION CAPTURE ACTOR\n" - "J.P. MANOUX\n\n" - "MOTION CAPTURE ACTRESS\n" - "SHAWN WOLFE"); - break; - - case MENU_CREDITS22: - mgametextcenter(origin.x, origin.y + (50<<16), "THIS GAME COULD NOT HAVE BEEN MADE WITHOUT\n" - "ALEX MAYBERRY\n" - "MAL BLACKWELL\n\n" - "NUTS AND BOLTS\n" - "STEVE GOLDBERG\n\n" - "BEAN COUNTING\n" - "MAX YOSHIKAWA\n\n" - "ADMINISTRATIVE ASSISTANCE\n" - "MINERVA MAYBERRY"); - break; - - case MENU_CREDITS23: - mgametextcenter(origin.x, origin.y + (60<<16), "FOR INTERPLAY\n\n" - "PRODUCER\n" - "BILL DUGAN\n\n" - "LINE PRODUCER\n" - "CHRIS BENSON\n\n" - "LEAD TESTER\n" - "DARRELL JONES"); - break; - - case MENU_CREDITS24: - mgametextcenter(origin.x, origin.y + (70<<16), "TESTERS\n\n" - "TIM ANDERSON\n" - "PRIMO PULANCO\n" - "MARK MCCARTY\n" - "BRIAN AXLINE"); - break; - - case MENU_CREDITS25: - mgametextcenter(origin.x, origin.y + (80<<16), "PRODUCTION BABY\n\n" - "PAULINE MARIE MARKHAM"); - break; - - case MENU_CREDITS26: - mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL PRODUCTION BABY\n\n" - "ALYSON KAUFMAN"); - break; - - case MENU_CREDITS27: - mgametextcenter(origin.x, origin.y + (80<<16), "3D BUILD ENGINE LICENSED FROM\n" - "3D REALMS ENTERTAINMENT\n\n" - "BUILD ENGINE AND RELATED TOOLS\n" - "CREATED BY KEN SILVERMAN"); - break; - - case MENU_CREDITS28: - mgametextcenter(origin.x, origin.y + (80<<16), "SPECIAL THANKS\n\n" - "SCOTT MILLER\n" - "GEORGE BROUSSARD"); - break; - - case MENU_CREDITS29: - mgametextcenter(origin.x, origin.y + (80<<16), "EXTRA SPECIAL THANKS\n\n" - "BRIAN FARGO"); - break; - - case MENU_CREDITS30: - mgametextcenter(origin.x, origin.y + (70<<16), "REDNECK RAMPAGE RIDES AGAIN\n" - "(c) 1998 XATRIX ENTERTAINMENT, INC.\n\n" - "REDNECK RAMPAGE RIDES AGAIN\n" - "IS A TRADEMARK OF\n" - "INTERPLAY PRODUCTIONS"); - break; - } - } - else - { - switch (cm) - { - case MENU_CREDITS: - mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL CONCEPT, DESIGN AND DIRECTION\n\n" - "DREW MARKHAM"); - break; - - case MENU_CREDITS2: - mgametextcenter(origin.x, origin.y + (80<<16), "PRODUCED BY\n\n" - "GREG GOODRICH"); - break; - - case MENU_CREDITS3: - mgametextcenter(origin.x, origin.y + (80<<16), "GAME PROGRAMMING\n\n" - "RAFAEL PAIZ"); - break; - - case MENU_CREDITS4: - mgametextcenter(origin.x, origin.y + (80<<16), "ART DIRECTORS\n\n" - "CLAIRE PRADERIE MAXX KAUFMAN "); - break; - - case MENU_CREDITS5: - mgametextcenter(origin.x, origin.y + (80<<16), "LEAD LEVEL DESIGNER\n" - "ALEX MAYBERRY\n\n" - "LEVEL DESIGN\n" - "MAL BLACKWELL\n" - "SVERRE KVERNMO"); - break; - - case MENU_CREDITS6: - mgametextcenter(origin.x, origin.y + (80<<16), "SENIOR ANIMATOR AND ARTIST\n\n" - "JASON HOOVER"); - break; - - case MENU_CREDITS7: - mgametextcenter(origin.x, origin.y + (80<<16), "TECHNICAL DIRECTOR\n\n" - "BARRY DEMPSEY"); - break; - - case MENU_CREDITS8: - mgametextcenter(origin.x, origin.y + (60<<16), "MOTION CAPTURE SPECIALIST AND\n" - "CHARACTER ANIMATION\n" - "AMIT DORON\n\n" - "A.I. PROGRAMMING\n" - "ARTHUR DONAVAN\n\n" - "ADDITIONAL ANIMATION\n" - "GEORGE KARL"); - break; - - case MENU_CREDITS9: - mgametextcenter(origin.x, origin.y + (50<<16), "CHARACTER DESIGN\n" - "CORKY LEHMKUHL\n\n" - "MAP PAINTERS\n" - "VIKTOR ANTONOV\n" - "MATTHIAS BEEGUER\n" - "STEPHAN BURLE\n\n" - "SCULPTORS\n" - "GEORGE ENGEL\n" - "JAKE GARBER\n" - "JEFF HIMMEL"); - break; - - case MENU_CREDITS10: - mgametextcenter(origin.x, origin.y + (40<<16), "CHARACTER VOICES\n\n" - "LEONARD\n" - "BURTON GILLIAM\n\n" - "BUBBA, BILLY RAY, SKINNY OL' COOT\n" - "AND THE TURD MINION\n" - "DREW MARKHAM\n\n" - "SHERIFF LESTER T. HOBBES\n" - "MOJO NIXON\n\n" - "ALIEN VIXEN\n" - "PEGGY JO JACOBS"); - break; - - case MENU_CREDITS11: - mgametextcenter(origin.x, origin.y + (50<<16), "SOUND DESIGN\n" - "GARY BRADFIELD\n\n" - "MUSIC\n" - "MOJO NIXON\n" - "THE BEAT FARMERS\n" - "THE REVEREND HORTON HEAT\n" - "CEMENT POND\n\n" - "ADDITIONAL SOUND EFFECTS\n" - "JIM SPURGIN"); - break; - - case MENU_CREDITS12: - mgametextcenter(origin.x, origin.y + (80<<16), "MOTION CAPTURE ACTOR\n" - "J.P. MANOUX\n\n" - "MOTION CAPTURE VIXEN\n" - "SHAWN WOLFE"); - break; - - case MENU_CREDITS13: - mgametextcenter(origin.x, origin.y + (50<<16), "PRODUCTION ASSISTANCE\n" - "MINERVA MAYBERRY\n\n" - "NUTS AND BOLTS\n" - "STEVE GOLDBERG\n" - "MARCUS HUTCHINSON\n\n" - "BEAN COUNTING\n" - "MAX YOSHIKAWA\n\n" - "ADMINISTRATIVE ASSISTANCE\n" - "SERAFIN LEWIS"); - break; - - case MENU_CREDITS14: - mgametextcenter(origin.x, origin.y + (70<<16), "LOCATION MANAGER, LOUISIANA\n" - "RICK SKINNER\n\n" - "LOCATION SCOUT, LOUISIANA\n" - "BRIAN BENOS\n\n" - "PHOTOGRAPHER\n" - "CARLOS SERRAO"); - break; - - case MENU_CREDITS15: - mgametextcenter(origin.x, origin.y + (50<<16), "ADDITIONAL 3D MODELING BY\n" - "3 NAME 3D\n" - "VIEWPOINT DATALABS INTERNATIONAL\n\n" - "AUDIO RECORDED AT\n" - "PACIFIC OCEAN POST, SANTA MONICA, C.A.\n\n" - "CEMENT POND TRACKS RECORDED AT\n" - "DREAMSTATE RECORDING, BURBANK, C.A.\n\n" - "RECORDING ENGINEER\n" - "DAVE AHLERT"); - break; - - case MENU_CREDITS16: - mgametextcenter(origin.x, origin.y + (80<<16), "3D BUILD ENGINE LICENSED FROM\n" - "3D REALMS ENTERTAINMENT\n\n" - "BUILD ENGINE AND RELATED TOOLS\n" - "CREATED BY KEN SILVERMAN"); - break; - - case MENU_CREDITS17: - mgametextcenter(origin.x, origin.y + (60<<16), "FOR INTERPLAY\n\n" - "LEAD TESTER\n" - "DARRELL JONES\n\n" - "TESTERS\n" - "TIM ANDERSON\n" - "ERICK LUJAN\n" - "TIEN TRAN"); - break; - - case MENU_CREDITS18: - mgametextcenter(origin.x, origin.y + (60<<16), "IS TECHS\n" - "BILL DELK\n" - "AARON MEYERS\n\n" - "COMPATIBILITY TECHS\n" - "MARC DURAN\n" - "DAN FORSYTH\n" - "DEREK GIBBS\n" - "AARON OLAIZ\n" - "JACK PARKER"); - break; - - case MENU_CREDITS19: - mgametextcenter(origin.x, origin.y + (70<<16), "DIRECTOR OF COMPATIBILITY\n" - "PHUONG NGUYEN\n\n" - "ASSISTANT QA DIRECTOR\n" - "COLIN TOTMAN\n\n" - "QA DIRECTOR\n" - "CHAD ALLISON"); - break; - - case MENU_CREDITS20: - mgametextcenter(origin.x, origin.y + (50<<16), "INTERPLAY PRODUCER\n" - "BILL DUGAN\n\n" - "INTERPLAY LINE PRODUCER\n" - "CHRIS BENSON\n\n" - "PRODUCT MANAGER\n" - "JIM VEEVAERT\n\n" - "PUBLIC RELATIONS\n" - "ERIKA PRICE"); - break; - - case MENU_CREDITS21: - mgametextcenter(origin.x, origin.y + (60<<16), "SPECIAL THANKS\n\n" - "JIM GAUER\n" - "PAUL VAIS\n" - "SCOTT MILLER\n" - "TODD REPLOGLE\n" - "CHUCK BUECHE\n" - "CARTER LIPSCOMB\n" - "JOHN CONLEY\n" - "DON MAGGI"); - break; - - case MENU_CREDITS22: - mgametextcenter(origin.x, origin.y + (80<<16), "EXTRA SPECIAL THANKS\n\n" - "BRIAN FARGO"); - break; - - case MENU_CREDITS23: - mgametextcenter(origin.x, origin.y + (60<<16), "REDNECK RAMPAGE\n" - "(c) 1997 XATRIX ENTERTAINMENT, INC.\n\n" - "REDNECK RAMPAGE IS A TRADEMARK OF\n" - "INTERPLAY PRODUCTIONS"); - break; - } - } - } - else if (!VOLUMEALL || !PLUTOPAK) - { - int32_t m; - switch (cm) - { - case MENU_CREDITS: - m = origin.x + (20<<16); - l = origin.y + (33<<16); - - shadowminitext(m, l, "Original Concept", 12); l += 7<<16; - shadowminitext(m, l, "Todd Replogle and Allen H. Blum III", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Produced & Directed By", 12); l += 7<<16; - shadowminitext(m, l, "Greg Malone", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Executive Producer", 12); l += 7<<16; - shadowminitext(m, l, "George Broussard", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "BUILD Engine", 12); l += 7<<16; - shadowminitext(m, l, "Ken Silverman", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Game Programming", 12); l += 7<<16; - shadowminitext(m, l, "Todd Replogle", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "3D Engine/Tools/Net", 12); l += 7<<16; - shadowminitext(m, l, "Ken Silverman", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Network Layer/Setup Program", 12); l += 7<<16; - shadowminitext(m, l, "Mark Dochtermann", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Map Design", 12); l += 7<<16; - shadowminitext(m, l, "Allen H. Blum III", 12); l += 7<<16; - shadowminitext(m, l, "Richard Gray", 12); l += 7<<16; - - m = origin.x + (180<<16); - l = origin.y + (33<<16); - - shadowminitext(m, l, "3D Modeling", 12); l += 7<<16; - shadowminitext(m, l, "Chuck Jones", 12); l += 7<<16; - shadowminitext(m, l, "Sapphire Corporation", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Artwork", 12); l += 7<<16; - shadowminitext(m, l, "Dirk Jones, Stephen Hornback", 12); l += 7<<16; - shadowminitext(m, l, "James Storey, David Demaret", 12); l += 7<<16; - shadowminitext(m, l, "Douglas R. Wood", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Sound Engine", 12); l += 7<<16; - shadowminitext(m, l, "Jim Dose", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Sound & Music Development", 12); l += 7<<16; - shadowminitext(m, l, "Robert Prince", 12); l += 7<<16; - shadowminitext(m, l, "Lee Jackson", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Voice Talent", 12); l += 7<<16; - shadowminitext(m, l, "Lani Minella - Voice Producer", 12); l += 7<<16; - shadowminitext(m, l, "Jon St. John as \"Duke Nukem\"", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Graphic Design", 12); l += 7<<16; - shadowminitext(m, l, "Packaging, Manual, Ads", 12); l += 7<<16; - shadowminitext(m, l, "Robert M. Atkins", 12); l += 7<<16; - shadowminitext(m, l, "Michael Hadwin", 12); l += 7<<16; - break; - - case MENU_CREDITS2: - m = origin.x + (20<<16); - l = origin.y + (33<<16); - - shadowminitext(m, l, "Special Thanks To", 12); l += 7<<16; - shadowminitext(m, l, "Steven Blackburn, Tom Hall", 12); l += 7<<16; - shadowminitext(m, l, "Scott Miller, Joe Siegler", 12); l += 7<<16; - shadowminitext(m, l, "Terry Nagy, Colleen Compton", 12); l += 7<<16; - shadowminitext(m, l, "HASH, Inc., FormGen, Inc.", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "The 3D Realms Beta Testers", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Nathan Anderson, Wayne Benner", 12); l += 7<<16; - shadowminitext(m, l, "Glenn Brensinger, Rob Brown", 12); l += 7<<16; - shadowminitext(m, l, "Erik Harris, Ken Heckbert", 12); l += 7<<16; - shadowminitext(m, l, "Terry Herrin, Greg Hively", 12); l += 7<<16; - shadowminitext(m, l, "Hank Leukart, Eric Baker", 12); l += 7<<16; - shadowminitext(m, l, "Jeff Rausch, Kelly Rogers", 12); l += 7<<16; - shadowminitext(m, l, "Mike Duncan, Doug Howell", 12); l += 7<<16; - shadowminitext(m, l, "Bill Blair", 12); l += 7<<16; - - m = origin.x + (160<<16); - l = origin.y + (33<<16); - - shadowminitext(m, l, "Company Product Support", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "The following companies were cool", 12); l += 7<<16; - shadowminitext(m, l, "enough to give us lots of stuff", 12); l += 7<<16; - shadowminitext(m, l, "during the making of Duke Nukem 3D.", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Altec Lansing Multimedia", 12); l += 7<<16; - shadowminitext(m, l, "for tons of speakers and the", 12); l += 7<<16; - shadowminitext(m, l, "THX-licensed sound system.", 12); l += 7<<16; - shadowminitext(m, l, "For info call 1-800-548-0620", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Creative Labs, Inc.", 12); l += 7<<16; - l += 3<<16; - shadowminitext(m, l, "Thanks for the hardware, guys.", 12); l += 7<<16; - break; - - case MENU_CREDITS3: - mgametextcenter(origin.x, origin.y + (50<<16), "Duke Nukem 3D is a trademark of\n" - "3D Realms Entertainment" - "\n" - "Duke Nukem 3D\n" - "(C) 1996 3D Realms Entertainment"); - - if (VOLUMEONE) - { - mgametextcenter(origin.x, origin.y + (106<<16), "Please read LICENSE.DOC for shareware\n" - "distribution grants and restrictions."); - } - mgametextcenter(origin.x, origin.y + ((VOLUMEONE?134:115)<<16), "Made in Dallas, Texas USA"); - break; - } - } - break; case MENU_CREDITS31: l = 7; @@ -3000,4495 +56,7 @@ static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin) break; - case MENU_CREDITS32: // JBF 20031220 - l = 7; - - mgametextcenter(origin.x, origin.y + ((50-l)<<16), "Developers"); - creditsminitext(origin.x + (160<<16), origin.y + ((50+10-l)<<16), "Richard \"TerminX\" Gobeille", 8); - creditsminitext(origin.x + (160<<16), origin.y + ((50+7+10-l)<<16), "Evan \"Hendricks266\" Ramos", 8); - - mgametextcenter(origin.x, origin.y + ((80-l)<<16), "Retired developers"); - creditsminitext(origin.x + (160<<16), origin.y + ((80+10-l)<<16), "Pierre-Loup \"Plagman\" Griffais", 8); - creditsminitext(origin.x + (160<<16), origin.y + ((80+7+10-l)<<16), "Philipp \"Helixhorned\" Kutin", 8); - - mgametextcenter(origin.x, origin.y + ((130+7-l)<<16), "Special thanks to"); - creditsminitext(origin.x + (160<<16), origin.y + ((130+7+10-l)<<16), "Jonathon \"JonoF\" Fowler", 8); - - mgametextcenter(origin.x, origin.y + ((150+7-l)<<16), "Uses BUILD Engine technology by"); - creditsminitext(origin.x + (160<<16), origin.y + ((150+7+10-l)<<16), "Ken \"Awesoken\" Silverman", 8); - - - break; - - case MENU_CREDITS33: - l = 7; - - mgametextcenter(origin.x, origin.y + ((38-l)<<16), "License and Other Contributors"); - { - static const char *header[] = - { - "This program is distributed under the terms of the", - "GNU General Public License version 2 as published by the", - "Free Software Foundation. See gpl-2.0.txt for details.", - "BUILD engine technology available under license. See buildlic.txt.", - nullptr, - "The EDuke32 team thanks the following people for their contributions:", - nullptr, - }; - static const char *body[] = - { - "Alex Dawson", // "pogokeen" - Polymost2, renderer work, bugfixes - "Bioman", // GTK work, APT repository and package upkeep - "Brandon Bergren", // "Bdragon" - tiles.cfg - "Charlie Honig", // "CONAN" - showview command - "Dan Gaskill", // "DeeperThought" - testing - "David Koenig", // "Bargle" - Merged a couple of things from duke3d_w32 - "Ed Coolidge", // Mapster32 improvements - "Emile Belanger", // original Android work - "Fox", // various patches - "Hunter_rus", // tons of stuff - "James Bentler", // Mapster32 improvements - "Jasper Foreman", // netcode contributions - "Javier Martinez", // "Malone3D" - EDuke 2.1.1 components - "Jeff Hart", // website graphics - "Jonathan Strander", // "Mblackwell" - testing and feature speccing - "Jordon Moss", // "Striker" - various patches, OldMP work - "Jose del Castillo", // "Renegado" - EDuke 2.1.1 components - "Lachlan McDonald", // official EDuke32 icon - "LSDNinja", // OS X help and testing - "Marcus Herbert", // "rhoenie" - OS X compatibility work - "Matthew Palmer", // "Usurper" - testing and eduke32.com domain - "Matt Saettler", // original DOS EDuke/WW2GI enhancements - "NY00123", // Linux / SDL usability patches - "Ozkan Sezer", // SDL/GTK version checking improvements - "Peter Green", // "Plugwash" - dynamic remapping, custom gametypes - "Peter Veenstra", // "Qbix" - port to 64-bit - "Robin Green", // CON array support - "Ryan Gordon", // "icculus" - icculus.org Duke3D port sound code - "Stephen Anthony", // early 64-bit porting work - "tueidj", // Wii port - }; - EDUKE32_STATIC_ASSERT(ARRAY_SIZE(body) % 3 == 0); - static const char *footer[] = - { - nullptr, - "Visit eduke32.com for news and updates", - }; - - static constexpr int header_numlines = ARRAY_SIZE(header); - static constexpr int body_numlines = ARRAY_SIZE(body); - static constexpr int footer_numlines = ARRAY_SIZE(footer); - - static constexpr int CCOLUMNS = 3; - static constexpr int CCOLXBUF = 20; - - int c; - i = 0; - for (c = 0; c < header_numlines; c++) - if (header[c]) - creditsminitext(origin.x + (160<<16), origin.y + ((17+10+10+8+4+(c*7)-l)<<16), header[c], 8); - i += c; - for (c = 0; c < body_numlines; c++) - if (body[c]) - creditsminitext(origin.x + ((CCOLXBUF+((320-CCOLXBUF*2)/(CCOLUMNS*2)) +((320-CCOLXBUF*2)/CCOLUMNS)*(c/(body_numlines/CCOLUMNS)))<<16), origin.y + ((17+10+10+8+4+((c%(body_numlines/CCOLUMNS))*7)+(i*7)-l)<<16), body[c], 8); - i += c/CCOLUMNS; - for (c = 0; c < footer_numlines; c++) - if (footer[c]) - creditsminitext(origin.x + (160<<16), origin.y + ((17+10+10+8+4+(c*7)+(i*7)-l)<<16), footer[c], 8); - } - - break; - - default: - break; - } -} - - -static void Menu_ReadSaveGameHeaders(); - -static void Menu_LoadReadHeaders() -{ - Menu_ReadSaveGameHeaders(); - - for (int i = 0; i < g_nummenusaves; ++i) - MenuEntry_DisableOnCondition(&ME_LOAD[i], g_menusaves[i].isOldVer); -} - -static void Menu_SaveReadHeaders() -{ - Menu_ReadSaveGameHeaders(); - - for (int i = 0; i < g_nummenusaves; ++i) - MenuEntry_LookDisabledOnCondition(&ME_SAVE[i], g_menusaves[i].isOldVer); -} - -static void Menu_PreInput(MenuEntry_t *entry) -{ - switch (g_currentMenu) - { - - case MENU_KEYBOARDKEYS: - if (inputState.GetKeyStatus(sc_Delete)) - { - Bindings.UnbindACommand(buttonMap.GetButtonName(M_KEYBOARDKEYS.currentEntry)); - S_PlaySound(RR ? 335 : KICK_HIT); - inputState.ClearKeyStatus(sc_Delete); - } - break; - - case MENU_LOAD: - if (inputState.GetKeyStatus(sc_Delete)) - { - inputState.ClearKeyStatus(sc_Delete); - if (M_LOAD.currentEntry < g_nummenusaves) - Menu_Change(MENU_LOADDELVERIFY); - } - break; - case MENU_SAVE: - if (inputState.GetKeyStatus(sc_Delete)) - { - inputState.ClearKeyStatus(sc_Delete); - if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves) - Menu_Change(MENU_SAVEDELVERIFY); - } - break; - - default: - break; - } -} - -static void Menu_PreOptionListDraw(MenuEntry_t *entry, const vec2_t origin) -{ - switch (g_currentMenu) - { - case MENU_MOUSEBTNS: - case MENU_MOUSEADVANCED: - case MENU_JOYSTICKBTNS: - case MENU_JOYSTICKAXIS: - mgametextcenter(origin.x, origin.y + (31<<16), "Select a function to assign"); - - Bsprintf(tempbuf, "to %s", entry->name); - - mgametextcenter(origin.x, origin.y + ((31+9)<<16), tempbuf); - - mgametextcenter(origin.x, origin.y + (161<<16), "Press \"Escape\" To Cancel"); - break; - } -} - -static int32_t Menu_PreCustom2ColScreen(MenuEntry_t *entry) -{ - if (g_currentMenu == MENU_KEYBOARDKEYS) - { - auto *column = (MenuCustom2Col_t*)entry->entry; - - int32_t sc = inputState.GetLastScanCode(); - if (sc != sc_None) - { - S_PlaySound(PISTOL_BODYHIT); - *column->column[M_KEYBOARDKEYS.currentColumn] = sc; - Bindings.SetBind(sc, buttonMap.GetButtonName(M_KEYBOARDKEYS.currentEntry)); - inputState.ClearKeyStatus(sc); - - return -1; - } - } - - return 0; -} - -static void Menu_PreCustom2ColScreenDraw(MenuEntry_t *entry, const vec2_t origin) -{ - if (g_currentMenu == MENU_KEYBOARDKEYS) - { - Bsprintf(tempbuf, "Press the key to assign as\n" - "%s for \"%s\"\n" - "\n" - "Press \"Escape\" To Cancel" - , M_KEYBOARDKEYS.currentColumn?"secondary":"primary", entry->name); - mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); - } -} - -static void Menu_EntryFocus(/*MenuEntry_t *entry*/) -{ - switch (g_currentMenu) - { - case MENU_LOAD: - if (M_LOAD.currentEntry < (int32_t)g_nummenusaves) - { - savebrief_t & sv = g_menusaves[M_LOAD.currentEntry].brief; - if (sv.isValid()) - G_LoadSaveHeaderNew(sv.path, &savehead); - } - break; - - case MENU_SAVE: - if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves) - { - savebrief_t & sv = g_menusaves[M_SAVE.currentEntry-1].brief; - if (sv.isValid()) - G_LoadSaveHeaderNew(sv.path, &savehead); - } - break; - - default: - break; - } -} - -static void Menu_StartGameWithoutSkill(void) -{ - ud.m_player_skill = M_SKILL.currentEntry+1; - - g_skillSoundVoice = S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - ud.m_respawn_monsters = 0; - - ud.m_monsters_off = ud.monsters_off = 0; - - ud.m_respawn_items = 0; - ud.m_respawn_inventory = 0; - - ud.multimode = 1; - - G_NewGame_EnterLevel(); -} - -static void Menu_DoCheat(int32_t cheatID) -{ - if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME)) - return; - - osdcmd_cheatsinfo_stat.cheatnum = cheatID; -} - -static int32_t Menu_Cheat_Warp(char const * const numbers) -{ - if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME)) - return 0; - - if (numbers == NULL || !numbers[0] || !numbers[1] || (VOLUMEALL && !numbers[2])) - return 1; - - if (VOLUMEALL) - { - osdcmd_cheatsinfo_stat.volume = numbers[0] - '0'; - osdcmd_cheatsinfo_stat.level = (numbers[1] - '0')*10+(numbers[2]-'0'); - } - else - { - osdcmd_cheatsinfo_stat.volume = numbers[0] - '0'; - osdcmd_cheatsinfo_stat.level = numbers[1] - '0'; - } - - osdcmd_cheatsinfo_stat.volume--; - osdcmd_cheatsinfo_stat.level--; - - if ((VOLUMEONE && osdcmd_cheatsinfo_stat.volume > 0) || osdcmd_cheatsinfo_stat.volume > g_volumeCnt-1 || - osdcmd_cheatsinfo_stat.level >= MAXLEVELS || g_mapInfo[osdcmd_cheatsinfo_stat.volume *MAXLEVELS+osdcmd_cheatsinfo_stat.level].filename == NULL) - return 1; - - osdcmd_cheatsinfo_stat.cheatnum = CHEAT_SCOTTY; - - return 0; -} - -static int32_t Menu_Cheat_Skill(char const * const number) -{ - if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME)) - return 0; - - if (number == NULL || !number[0]) - return 1; - - osdcmd_cheatsinfo_stat.volume = number[0] - '1'; - - osdcmd_cheatsinfo_stat.cheatnum = CHEAT_SKILL; - - return 0; -} - -/* -Functions where a "newValue" or similar is passed are run *before* the linked variable is actually changed. -That way you can compare the new and old values and potentially block the change. -*/ -static void Menu_EntryLinkActivate(MenuEntry_t *entry) -{ - switch (g_currentMenu) - { - case MENU_EPISODE: - if (entry != &ME_EPISODE_USERMAP) - { - ud.m_volume_number = M_EPISODE.currentEntry; - m_level_number = 0; - - if (g_skillCnt == 0) - Menu_StartGameWithoutSkill(); - } - break; - - case MENU_SKILL: - { - int32_t skillsound = RR ? 341 : PISTOL_BODYHIT; - - if (RR) - switch (M_SKILL.currentEntry) - { - case 0: - skillsound = 427; - break; - case 1: - skillsound = 428; - break; - case 2: - skillsound = 196; - break; - case 3: - skillsound = 195; - break; - case 4: - skillsound = 197; - break; - } - else - switch (M_SKILL.currentEntry) - { - case 0: - skillsound = JIBBED_ACTOR6; - break; - case 1: - skillsound = BONUS_SPEECH1; - break; - case 2: - skillsound = DUKE_GETWEAPON2; - break; - case 3: - skillsound = JIBBED_ACTOR5; - break; - } - - ud.m_player_skill = M_SKILL.currentEntry+(RRRA ? 0 : 1); - - g_skillSoundVoice = S_PlaySound(skillsound); - - if (M_SKILL.currentEntry == 3) ud.m_respawn_monsters = 1; - else ud.m_respawn_monsters = 0; - - ud.m_monsters_off = ud.monsters_off = 0; - - ud.m_respawn_items = 0; - ud.m_respawn_inventory = 0; - - ud.multimode = 1; - - G_NewGame_EnterLevel(); - break; - } - - case MENU_JOYSTICKAXES: - M_JOYSTICKAXIS.title = joyGetName(0, M_JOYSTICKAXES.currentEntry); -#if 0 - MEO_JOYSTICKAXIS_ANALOG.data = &JoystickAnalogueAxes[M_JOYSTICKAXES.currentEntry]; - MEO_JOYSTICKAXIS_SCALE.variable = &JoystickAnalogueScale[M_JOYSTICKAXES.currentEntry]; - MEO_JOYSTICKAXIS_DEAD.variable = &JoystickAnalogueDead[M_JOYSTICKAXES.currentEntry]; - MEO_JOYSTICKAXIS_SATU.variable = &JoystickAnalogueSaturate[M_JOYSTICKAXES.currentEntry]; - MEO_JOYSTICKAXIS_DIGITALNEGATIVE.data = &JoystickDigitalFunctions[M_JOYSTICKAXES.currentEntry][0]; - MEO_JOYSTICKAXIS_DIGITALPOSITIVE.data = &JoystickDigitalFunctions[M_JOYSTICKAXES.currentEntry][1]; -#endif - break; - - case MENU_CHEATS: - { - const int32_t cheatFuncID = M_CHEATS.currentEntry - 1; - switch (cheatFuncID) - { - case -1: - case CHEATFUNC_WARP: - case CHEATFUNC_SKILL: - break; - default: - Menu_DoCheat(CheatFunctionIDs[cheatFuncID]); - break; - } - break; - } - - default: - break; - } - - if (entry == &ME_VIDEOSETUP_APPLY) - { - resolution_t p = { xres, yres, fullscreen, bpp, 0 }; - int32_t prend = videoGetRenderMode(); - int32_t pvsync = vid_vsync; - - resolution_t n = { resolution[newresolution].xdim, resolution[newresolution].ydim, - (resolution[newresolution].flags & RES_FS) ? newfullscreen : 0, - (newrendermode == REND_CLASSIC) ? 8 : resolution[newresolution].bppmax, 0 }; - int32_t nrend = newrendermode; - int32_t nvsync = newvsync; - - if (videoSetGameMode(n.flags, n.xdim, n.ydim, n.bppmax, upscalefactor) < 0) - { - if (videoSetGameMode(p.flags, p.xdim, p.ydim, p.bppmax, upscalefactor) < 0) - { - videoSetRenderMode(prend); - G_GameExit("Failed restoring old video mode."); - } - else - { - onvideomodechange(p.bppmax > 8); - vid_vsync = videoSetVsync(pvsync); - } - } - else onvideomodechange(n.bppmax > 8); - - g_restorePalette = -1; - G_UpdateScreenArea(); - videoSetRenderMode(nrend); - vid_vsync = videoSetVsync(nvsync); - ScreenMode = fullscreen; - ScreenWidth = xres; - ScreenHeight = yres; - ScreenBPP = bpp; - } - else if (entry == &ME_SOUND_RESTART) - { - snd_mixrate = soundrate; - snd_numvoices = soundvoices; - - S_SoundShutdown(); - S_MusicShutdown(); - - S_MusicStartup(); - S_SoundStartup(); - - FX_StopAllSounds(); - S_ClearSoundLocks(); - - if (MusicEnabled()) - S_RestartMusic(); - } - else if (entry == &ME_SAVESETUP_CLEANUP) - { - g_oldSaveCnt = G_CountOldSaves(); - Menu_Change(MENU_SAVECLEANVERIFY); - } - else if (entry == &ME_COLCORR_RESET) - { - vid_gamma = 1.f; - vid_contrast = 1.f; - vid_brightness = 0.f; - r_ambientlight = 1.f; - videoSetPalette(0,g_player[myconnectindex].ps->palette,0); - } - else if (entry == &ME_KEYBOARDSETUP_RESET) - CONFIG_SetDefaultKeys("demolition/defbinds.txt"); - else if (entry == &ME_KEYBOARDSETUP_RESETCLASSIC) - CONFIG_SetDefaultKeys("demolition/origbinds.txt"); - else if (entry == &ME_NETHOST_LAUNCH) - { - // master does whatever it wants - if (g_netServer) - { - Net_FillNewGame(&pendingnewgame, 1); - Net_SendNewGame(1, NULL); - Net_StartNewGame(); - } - else if (voting == -1) - { - Net_SendMapVoteInitiate(); - Menu_Change(MENU_NETWAITVOTES); - } - } -} - -static int32_t Menu_EntryOptionModify(MenuEntry_t *entry, int32_t newOption) -{ - int32_t x; - DukePlayer_t *ps = g_player[myconnectindex].ps; - - if (entry == &ME_GAMESETUP_DEMOREC) - { - if ((ps->gm&MODE_GAME)) - G_CloseDemoWrite(); - } - else if (entry == &ME_GAMESETUP_WEAPSWITCH_PICKUP) - { - ud.weaponswitch = ud.weaponswitch & ~(1|4); - switch (newOption) - { - case 2: - ud.weaponswitch = ud.weaponswitch | 4; - fallthrough__; - case 1: - ud.weaponswitch = ud.weaponswitch | 1; - break; - default: - break; - } - } - else if (entry == &ME_SOUND) - { - if (newOption == 0) - { - FX_StopAllSounds(); - S_ClearSoundLocks(); - } - } - else if (entry == &ME_SOUND_MUSIC || entry == &ME_CDPLAYER_TRACK) - { - mus_enabled = newOption; - - if (newOption == 0) - S_PauseMusic(true); - else - { - S_RestartMusic(); - S_PauseMusic(false); - } - } - else if (entry == &ME_SOUND_DUKETALK) - snd_speech = (snd_speech&~1) | newOption; - else if (entry == &ME_JOYSTICKAXIS_ANALOG) - CONTROL_MapAnalogAxis(M_JOYSTICKAXES.currentEntry, newOption, controldevice_joystick); - else if (entry == &ME_NETOPTIONS_EPISODE) - { - if (newOption < g_volumeCnt) - ud.m_volume_number = newOption; - } - else if (entry == &ME_NETOPTIONS_MONSTERS) - { - ud.m_monsters_off = (newOption == g_skillCnt); - if (newOption < g_skillCnt) - ud.m_player_skill = newOption; - } - else if (entry == &ME_ADULTMODE) - { - if (newOption) - { - for (x=0; x>1, newOption, i&1, controldevice_joystick); - } - break; - } - - return 0; -} - -static void Menu_EntryOptionDidModify(MenuEntry_t *entry) -{ -#ifdef USE_OPENGL - int domodechange = 0; -#endif - - if (entry == &ME_GAMESETUP_AIM_AUTO || - entry == &ME_GAMESETUP_WEAPSWITCH_PICKUP || - //entry == &ME_PLAYER_NAME || - entry == &ME_PLAYER_COLOR || - entry == &ME_PLAYER_TEAM) - G_UpdatePlayerFromMenu(); -#ifdef USE_OPENGL - else if (entry == &ME_DISPLAYSETUP_ANISOTROPY || entry == &ME_DISPLAYSETUP_TEXFILTER) - gltexapplyprops(); - - if (domodechange) - { - videoResetMode(); - if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor)) - OSD_Printf("restartvid: Reset failed...\n"); - onvideomodechange(ScreenBPP>8); - G_RefreshLights(); - } -#endif -} - -static void Menu_Custom2ColScreen(/*MenuEntry_t *entry*/) -{ - if (g_currentMenu == MENU_KEYBOARDKEYS) - { - inputState.keyFlushChars(); - inputState.ClearLastScanCode(); - } -} - -static int32_t Menu_EntryRangeInt32Modify(MenuEntry_t *entry, int32_t newValue) -{ - if (entry == &ME_SCREENSETUP_SBARSIZE) - G_SetStatusBarScale(newValue); - else if (entry == &ME_SOUND_VOLUME_FX) - FX_SetVolume(newValue); - else if (entry == &ME_SOUND_VOLUME_MUSIC) - S_MusicVolume(newValue); - else if (entry == &ME_JOYSTICKAXIS_SCALE) - CONTROL_SetAnalogAxisScale(M_JOYSTICKAXES.currentEntry, newValue, controldevice_joystick); - else if (entry == &ME_JOYSTICKAXIS_DEAD) - joySetDeadZone(M_JOYSTICKAXES.currentEntry, newValue, *MEO_JOYSTICKAXIS_SATU.cVar); - else if (entry == &ME_JOYSTICKAXIS_SATU) - joySetDeadZone(M_JOYSTICKAXES.currentEntry, *MEO_JOYSTICKAXIS_DEAD.cVar, newValue); - - return 0; -} - -static int32_t Menu_EntryRangeFloatModify(MenuEntry_t *entry, float newValue) -{ -#ifndef EDUKE32_SIMPLE_MENU - if (entry == &ME_COLCORR_AMBIENT) - r_ambientlightrecip = 1.f/newValue; -#else - UNREFERENCED_PARAMETER(entry); - UNREFERENCED_PARAMETER(newValue); -#endif - - return 0; -} - -static int32_t Menu_EntryRangeFloatDidModify(MenuEntry_t *entry) -{ - return 0; -} - -#ifdef MENU_ENABLE_RANGEDOUBLE -static int32_t Menu_EntryRangeDoubleModify(void /*MenuEntry_t *entry, double newValue*/) -{ - - return 0; -} -#endif - -static uint32_t save_xxh = 0; - -static void Menu_EntryStringActivate(/*MenuEntry_t *entry*/) -{ - switch (g_currentMenu) - { - case MENU_SAVE: - if (M_SAVE.currentEntry > 0) - { - savebrief_t & sv = g_menusaves[M_SAVE.currentEntry-1].brief; - if (!save_xxh) - save_xxh = SuperFastHash(sv.name, MAXSAVEGAMENAME); - if (sv.isValid()) - Menu_Change(MENU_SAVEVERIFY); - } - else - { - ME_SAVE_NEW.name = nullptr; - save_xxh = 0; - } - break; - - default: - break; - } -} - -static int32_t Menu_EntryStringSubmit(/*MenuEntry_t *entry, */char *input) -{ - int32_t returnvar = 0; - - switch (g_currentMenu) - { - case MENU_SAVE: - { - savebrief_t & sv = g_lastusersave = M_SAVE.currentEntry == 0 ? savebrief_t{input} : g_menusaves[M_SAVE.currentEntry-1].brief; - - // dirty hack... char 127 in last position indicates an auto-filled name -#ifdef __ANDROID__ - if (1) -#else - if (input[0] == 0 || (sv.name[MAXSAVEGAMENAME] == 127 && - strncmp(sv.name, input, MAXSAVEGAMENAME) == 0 && - save_xxh == SuperFastHash(sv.name, MAXSAVEGAMENAME))) -#endif - { - strncpy(sv.name, g_mapInfo[ud.volume_number * MAXLEVELS + ud.level_number].name, MAXSAVEGAMENAME); - sv.name[MAXSAVEGAMENAME] = 127; - returnvar = -1; - } - else - { - strncpy(sv.name, input, MAXSAVEGAMENAME); - sv.name[MAXSAVEGAMENAME] = 0; - } - - G_SavePlayerMaybeMulti(sv); - - g_quickload = &sv; - g_player[myconnectindex].ps->gm = MODE_GAME; - - Menu_Change(MENU_CLOSE); - save_xxh = 0; - break; - } - - default: - break; - } - - return returnvar; -} - -static void Menu_EntryStringCancel(/*MenuEntry_t *entry*/) -{ - switch (g_currentMenu) - { - case MENU_SAVE: - save_xxh = 0; - ME_SAVE_NEW.name = s_NewSaveGame; - break; - - default: - break; - } -} - -/* -This is polled when the menu code is populating the screen but for some reason doesn't have the data. -*/ -static int32_t Menu_EntryOptionSource(MenuEntry_t *entry, int32_t currentValue) -{ - if (entry == &ME_GAMESETUP_WEAPSWITCH_PICKUP) - return (cl_weaponswitch & 1) ? ((cl_weaponswitch & 4) ? 2 : 1) : 0; - else if (entry == &ME_SOUND_DUKETALK) - return snd_speech & 1; - else if (entry == &ME_NETOPTIONS_MONSTERS) - return (ud.m_monsters_off ? g_skillCnt : ud.m_player_skill); - - return currentValue; -} - -static void Menu_Verify(int32_t input) -{ - switch (g_currentMenu) - { - case MENU_SAVECLEANVERIFY: - if (input) - { - G_DeleteOldSaves(); - } - break; - - case MENU_RESETPLAYER: - switch (input) - { - default: - inputState.keyFlushChars(); - inputState.ClearKeysDown(); - FX_StopAllSounds(); - - if (G_LoadPlayerMaybeMulti(*g_quickload) == 0) - break; - - // error state, consider as a no instead of yes - g_quickload->reset(); - - fallthrough__; - case 0: - if (sprite[g_player[myconnectindex].ps->i].extra <= 0) - { - if (G_EnterLevel(MODE_GAME)) G_BackToMenu(); - return; - } - - Menu_Change(MENU_CLOSE); - break; - } - break; - - case MENU_LOADVERIFY: - if (input) - { - savebrief_t & sv = g_menusaves[M_LOAD.currentEntry].brief; - - if (strcmp(sv.path, g_lastusersave.path) != 0) - { - g_freshload = sv; - g_lastusersave.reset(); - g_lastautosave.reset(); - g_quickload = &g_freshload; - } - else - { - g_quickload = &g_lastusersave; - } - - inputState.keyFlushChars(); - inputState.ClearKeysDown(); - - Menu_Change(MENU_CLOSE); - - G_LoadPlayerMaybeMulti(sv); - } - break; - - case MENU_SAVEVERIFY: - if (!input) - { - save_xxh = 0; - - ((MenuString_t*)M_SAVE.entrylist[M_SAVE.currentEntry]->entry)->editfield = NULL; - } - break; - - case MENU_LOADDELVERIFY: - if (input) - { - G_DeleteSave(g_menusaves[M_LOAD.currentEntry].brief); - Menu_LoadReadHeaders(); - M_LOAD.currentEntry = clamp(M_LOAD.currentEntry, 0, (int32_t)g_nummenusaves-1); - } - break; - case MENU_SAVEDELVERIFY: - if (input) - { - G_DeleteSave(g_menusaves[M_SAVE.currentEntry-1].brief); - Menu_SaveReadHeaders(); - M_SAVE.currentEntry = clamp(M_SAVE.currentEntry, 0, (int32_t)g_nummenusaves); - } - break; - - case MENU_QUIT: - case MENU_QUIT_INGAME: - if (input) - G_GameQuit(); - else - g_quitDeadline = 0; - break; - - case MENU_QUITTOTITLE: - if (input) - { - g_player[myconnectindex].ps->gm = MODE_DEMO; - if (ud.recstat == 1) - G_CloseDemoWrite(); - artClearMapArt(); - } - break; - - case MENU_NETWAITVOTES: - if (!input) - Net_SendMapVoteCancel(0); - break; - - default: - break; - } -} - -static int Menu_CheatStringMatch(char const * input, char const * cheat) -{ - while (*cheat || *input) - { - if (*cheat != *input) - { - if (!(*cheat == '#' && Bisdigit(*input))) - return 0; - } - - ++cheat; - ++input; - } - - return 1; -} - -static void Menu_TextFormSubmit(char *input) -{ - switch (g_currentMenu) - { - case MENU_ADULTPASSWORD: - break; - - case MENU_CHEATENTRY: - { - const size_t inputlength = Bstrlen(input); - Bstrcpy(tempbuf, input); - for (size_t i = 0; i < inputlength; i++) - tempbuf[i] = Btolower(tempbuf[i]); - - int8_t cheatID = -1; - - if (inputlength > 2 && tempbuf[0] == g_keyAsciiTable[CheatKeys[0]] && tempbuf[1] == g_keyAsciiTable[CheatKeys[1]]) - { - for (int i = 0; i < NUMCHEATS; i++) - if (Menu_CheatStringMatch(tempbuf+2, CheatStrings[i])) - { - cheatID = i; - break; - } - } - - switch (cheatID) - { - case -1: - S_PlaySound(RR ? 335 : KICK_HIT); - break; - case CHEAT_SCOTTY: - { - char const * const numberpos = Bstrchr(CheatStrings[CHEAT_SCOTTY], '#'); - if (numberpos == NULL) - { - S_PlaySound(RR ? 335 : KICK_HIT); - break; - } - - Menu_Cheat_Warp(input + (numberpos - CheatStrings[CHEAT_SCOTTY]) + 2); - if (g_player[myconnectindex].ps->gm&MODE_MENU) - S_PlaySound(DUKE_GET); - break; - } - case CHEAT_SKILL: - { - char const * const numberpos = Bstrchr(CheatStrings[CHEAT_SKILL], '#'); - if (numberpos == NULL) - { - S_PlaySound(RR ? 335 : KICK_HIT); - break; - } - - Menu_Cheat_Skill(input + (numberpos - CheatStrings[CHEAT_SKILL]) + 2); - if (g_player[myconnectindex].ps->gm&MODE_MENU) - S_PlaySound(DUKE_GET); - break; - } - default: - Menu_DoCheat(cheatID); - S_PlaySound(DUKE_GET); - break; - } - - if (cheatID >= 0) - cl_cheatmask = cl_cheatmask | CheatFunctionFlags[cheatID]; - - if (((cl_cheatmask & (1<fnlist); - - if (object->destination[0] == 0) - Bstrcpy(object->destination, "./"); - Bcorrectfilename(object->destination, 1); - - fnlist_getnames(&object->fnlist, object->destination, object->pattern, 0, 0); - object->findhigh[0] = object->fnlist.finddirs; - object->findhigh[1] = object->fnlist.findfiles; - - for (int i = 0; i < 2; ++i) - { - object->scrollPos[i] = 0; - klistbookends(object->findhigh[i]); - } - - object->currentList = 0; - if (object->findhigh[1]) - object->currentList = 1; #endif - inputState.keyFlushChars(); -} - -static void Menu_FileSelect(int32_t input) -{ -#if 0 - switch (g_currentMenu) - { - case MENU_NETUSERMAP: - if ((g_netServer || ud.multimode > 1)) - Net_SendUserMapName(); - fallthrough__; - case MENU_USERMAP: - if (input) - { - ud.m_volume_number = 0; - m_level_number = 7; - - if (g_skillCnt > 0) - Menu_AnimateChange(MENU_SKILL, MA_Advance); - else - Menu_StartGameWithoutSkill(); - } - break; - - default: - break; - } -#endif -} - - - - - -static Menu_t* Menu_BinarySearch(MenuID_t query, uint16_t searchstart, uint16_t searchend) -{ - const uint16_t thissearch = (searchstart + searchend) / 2; - const MenuID_t difference = query - Menus[thissearch].menuID; - - if (difference == 0) - return &Menus[thissearch]; - else if (searchstart == searchend) - return NULL; - else if (difference > 0) - { - if (thissearch == searchend) - return NULL; - searchstart = thissearch + 1; - } - else if (difference < 0) - { - if (thissearch == searchstart) - return NULL; - searchend = thissearch - 1; - } - - return Menu_BinarySearch(query, searchstart, searchend); -} - -static Menu_t* Menu_Find(MenuID_t query) -{ - if ((unsigned) query > (unsigned) Menus[numMenus-1].menuID) - return NULL; - - return Menu_BinarySearch(query, 0, numMenus-1); -} - -static Menu_t* Menu_FindFiltered(MenuID_t query) -{ - if ((g_player[myconnectindex].ps->gm&MODE_GAME) && query == MENU_MAIN) - query = MENU_MAIN_INGAME; - - return Menu_Find(query); -} - -MenuAnimation_t m_animation; - -int32_t Menu_Anim_SinOutRight(MenuAnimation_t *animdata) -{ - return sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] - 16384; -} -int32_t Menu_Anim_SinInRight(MenuAnimation_t *animdata) -{ - return sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] + 16384; -} -int32_t Menu_Anim_SinOutLeft(MenuAnimation_t *animdata) -{ - return -sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] + 16384; -} -int32_t Menu_Anim_SinInLeft(MenuAnimation_t *animdata) -{ - return -sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] - 16384; -} - -void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype) -{ - if (cm == MENU_KEYBOARDKEYS) - { - GUICapture |= 2; - return; - } - - switch (animtype) - { - case MA_Advance: - { - Menu_t * const previousMenu = m_currentMenu; - - if (!Menu_Change(cm)) - { - m_animation.out = Menu_Anim_SinOutRight; - m_animation.in = Menu_Anim_SinInRight; - m_animation.start = (int32_t) totalclock; - m_animation.length = 30; - - m_animation.previous = previousMenu; - m_animation.current = m_currentMenu; - } - - break; - } - case MA_Return: - { - Menu_t * const previousMenu = m_currentMenu; - - if (!Menu_Change(cm)) - { - m_animation.out = Menu_Anim_SinOutLeft; - m_animation.in = Menu_Anim_SinInLeft; - m_animation.start = (int32_t) totalclock; - m_animation.length = 30; - - m_animation.previous = previousMenu; - m_animation.current = m_currentMenu; - } - - break; - } - default: - m_animation.start = 0; - m_animation.length = 0; - Menu_Change(cm); - break; - } -} - -static void Menu_MaybeSetSelectionToChild(Menu_t * m, MenuID_t id) -{ - if (m->type == Menu) - { - auto * menu = (MenuMenu_t *)m->object; - - if (menu->currentEntry < menu->numEntries) - { - MenuEntry_t const * currentEntry = menu->entrylist[menu->currentEntry]; - if (currentEntry != NULL && currentEntry->type == Link) - { - auto const * link = (MenuLink_t const *)currentEntry->entry; - if (link->linkID == id) - return; // already good to go - } - } - - for (int i = 0, i_end = menu->numEntries; i < i_end; ++i) - { - MenuEntry_t const * entry = menu->entrylist[i]; - if (entry != NULL && entry->type == Link && !(entry->flags & MEF_Hidden)) - { - auto const * link = (MenuLink_t const *)entry->entry; - if (link->linkID == id) - { - menu->currentEntry = i; - Menu_AdjustForCurrentEntryAssignmentBlind(menu); - break; - } - } - } - } -} - -static void Menu_ReadSaveGameHeaders() -{ - ReadSaveGameHeaders(); - - int const numloaditems = max(g_nummenusaves, 1), numsaveitems = g_nummenusaves+1; - ME_LOAD = (MenuEntry_t *)Xrealloc(ME_LOAD, g_nummenusaves * sizeof(MenuEntry_t)); - MEL_LOAD = (MenuEntry_t **)Xrealloc(MEL_LOAD, numloaditems * sizeof(MenuEntry_t *)); - MEO_SAVE = (MenuString_t *)Xrealloc(MEO_SAVE, g_nummenusaves * sizeof(MenuString_t)); - ME_SAVE = (MenuEntry_t *)Xrealloc(ME_SAVE, g_nummenusaves * sizeof(MenuEntry_t)); - MEL_SAVE = (MenuEntry_t **)Xrealloc(MEL_SAVE, numsaveitems * sizeof(MenuEntry_t *)); - - MEL_SAVE[0] = &ME_SAVE_NEW; - ME_SAVE_NEW.name = s_NewSaveGame; - for (int i = 0; i < g_nummenusaves; ++i) - { - MEL_LOAD[i] = &ME_LOAD[i]; - MEL_SAVE[i+1] = &ME_SAVE[i]; - ME_LOAD[i] = ME_LOAD_TEMPLATE; - ME_SAVE[i] = ME_SAVE_TEMPLATE; - ME_SAVE[i].entry = &MEO_SAVE[i]; - MEO_SAVE[i] = MEO_SAVE_TEMPLATE; - - ME_LOAD[i].name = g_menusaves[i].brief.name; - MEO_SAVE[i].variable = g_menusaves[i].brief.name; - } - - if (g_nummenusaves == 0) - MEL_LOAD[0] = &ME_LOAD_EMPTY; - - M_LOAD.entrylist = MEL_LOAD; - M_LOAD.numEntries = numloaditems; - M_SAVE.entrylist = MEL_SAVE; - M_SAVE.numEntries = numsaveitems; - - // lexicographical sorting? -} - -static void Menu_AboutToStartDisplaying(Menu_t * m) -{ - switch (m->menuID) - { - case MENU_MAIN: - break; - - case MENU_MAIN_INGAME: - break; - - case MENU_LOAD: - Menu_LoadReadHeaders(); - - if (g_quickload && g_quickload->isValid()) - { - for (int i = 0; i < g_nummenusaves; ++i) - { - if (strcmp(g_menusaves[i].brief.path, g_quickload->path) == 0) - { - M_LOAD.currentEntry = i; - Menu_AdjustForCurrentEntryAssignmentBlind(&M_LOAD); - break; - } - } - } - break; - - case MENU_SAVE: - if (g_previousMenu == MENU_SAVEVERIFY || g_previousMenu == MENU_SAVEDELVERIFY) - break; - - Menu_SaveReadHeaders(); - - if (g_lastusersave.isValid()) - { - for (int i = 0; i < g_nummenusaves; ++i) - { - if (strcmp(g_menusaves[i].brief.path, g_lastusersave.path) == 0) - { - M_SAVE.currentEntry = i+1; - Menu_AdjustForCurrentEntryAssignmentBlind(&M_SAVE); - break; - } - } - } - - if (g_player[myconnectindex].ps->gm&MODE_GAME) - { - g_screenCapture = 1; - G_DrawRooms(myconnectindex,65536); - g_screenCapture = 0; - } - break; - - case MENU_VIDEOSETUP: - newresolution = 0; - for (int i = 0; i < MAXVALIDMODES; ++i) - { - if (resolution[i].xdim == xres && resolution[i].ydim == yres) - { - newresolution = i; - break; - } - } - newrendermode = videoGetRenderMode(); - newfullscreen = fullscreen; - newvsync = vid_vsync; - break; - - case MENU_ADVSOUND: - soundrate = snd_mixrate; - soundvoices = snd_numvoices; - break; - - default: - break; - } - - switch (m->type) - { - case TextForm: - typebuf[0] = 0; - ((MenuTextForm_t*)m->object)->input = typebuf; - break; - case FileSelect: - Menu_FileSelectInit((MenuFileSelect_t*)m->object); - break; - case CdPlayer: - { - auto *menu = (MenuMenu_t*)m->object; - menu->currentEntry = g_cdTrack-2; - // MenuEntry_t* currentry = menu->entrylist[menu->currentEntry]; - - if (menu->currentEntry < 0 || menu->currentEntry >= menu->numEntries) - menu->currentEntry = 0; - - Menu_EntryFocus(/*currentry*/); - break; - } - case Menu: - { - auto *menu = (MenuMenu_t*)m->object; - // MenuEntry_t* currentry = menu->entrylist[menu->currentEntry]; - - // need this for MENU_SKILL - if (menu->currentEntry >= menu->numEntries) - menu->currentEntry = 0; - - int32_t i = menu->currentEntry; - while (!menu->entrylist[menu->currentEntry] || - (((MenuEntry_t*)menu->entrylist[menu->currentEntry])->flags & MEF_Hidden) || - ((MenuEntry_t*)menu->entrylist[menu->currentEntry])->type == Spacer) - { - menu->currentEntry++; - if (menu->currentEntry >= menu->numEntries) - menu->currentEntry = 0; - if (menu->currentEntry == i) - G_GameExit("Menu_Change: Attempted to show a menu with no entries."); - } - - Menu_EntryFocus(/*currentry*/); - break; - } - default: - break; - } -} - -static void Menu_ChangingTo(Menu_t * m) -{ -#ifdef __ANDROID__ - if (m->menuID == MENU_TOUCHBUTTONS) - AndroidToggleButtonEditor(); -#endif - - switch (m->type) - { - case TextForm: - Menu_StartTextInput(); - break; - default: - break; - } -} - -int Menu_Change(MenuID_t cm) -{ - Menu_t * beginMenu = m_currentMenu; - - if (cm == MENU_PREVIOUS) - { - m_currentMenu = m_previousMenu; - g_currentMenu = g_previousMenu; - } - else if (cm == MENU_CLOSE) - Menu_Close(myconnectindex); - else if (cm >= 0) - { - Menu_t * search = Menu_FindFiltered(cm); - - if (search == NULL) - return 0; // intentional, so that users don't use any random value as "don't change" - - // security - if (search->type == Verify && - search->parentID != MENU_PREVIOUS && - search->parentID != MENU_CLOSE && - search->parentID != g_currentMenu) - return 1; - - m_previousMenu = m_currentMenu; - g_previousMenu = g_currentMenu; - m_currentMenu = search; - g_currentMenu = search->menuID; - } - else - return 1; - - Menu_MaybeSetSelectionToChild(m_currentMenu, beginMenu->menuID); - Menu_AboutToStartDisplaying(m_currentMenu); - Menu_ChangingTo(m_currentMenu); - -#if !defined EDUKE32_TOUCH_DEVICES - m_menuchange_watchpoint = 1; -#endif - - return 0; -} - - - - - - - - - - -int G_CheckPlayerColor(int color) -{ - for (int i : MEOSV_PLAYER_COLOR) - if (i == color) - return color; - - return -1; -} - - -int32_t Menu_DetermineSpecialState(MenuEntry_t *entry) -{ - if (entry == NULL) - return 0; - - if (entry->type == String) - { - if (((MenuString_t*)entry->entry)->editfield) - return 1; - } - else if (entry->type == Option) - { - if (((MenuOption_t*)entry->entry)->options->currentEntry >= 0) - return 2; - } - else if (entry->type == Custom2Col) - { - if (((MenuCustom2Col_t*)entry->entry)->screenOpen) - return 2; - } - - return 0; -} - -int32_t Menu_IsTextInput(Menu_t *cm) -{ - switch (m_currentMenu->type) - { - case Verify: - case TextForm: - case FileSelect: - case Message: - return 1; - break; - case Panel: - case CdPlayer: - return 0; - break; - case Menu: - { - auto *menu = (MenuMenu_t *)cm->object; - auto *entry = menu->entrylist[menu->currentEntry]; - return Menu_DetermineSpecialState(entry); - } - break; - } - - return 0; -} - -static inline int32_t Menu_BlackTranslucentBackgroundOK(MenuID_t cm) -{ - switch (cm) - { - case MENU_COLCORR: - case MENU_COLCORR_INGAME: - return 0; - break; - default: - return 1; - break; - } - - return 1; -} - -static inline int32_t Menu_UpdateScreenOK(MenuID_t cm) -{ - switch (cm) - { - case MENU_LOAD: - case MENU_SAVE: - case MENU_LOADVERIFY: - case MENU_LOADDELVERIFY: - case MENU_SAVEVERIFY: - case MENU_SAVEDELVERIFY: - return 0; - break; - default: - return 1; - break; - } - - return 1; -} - - -/* - Code below this point is entirely general, - so if you want to change or add a menu, - chances are you should scroll up. -*/ - -int32_t m_mouselastactivity; -#if !defined EDUKE32_TOUCH_DEVICES -int32_t m_mousewake_watchpoint, m_menuchange_watchpoint; -#endif -int32_t m_mousecaught; -static vec2_t m_prevmousepos, m_mousepos, m_mousedownpos; - -void Menu_Open(uint8_t playerID) -{ - g_player[playerID].ps->gm |= MODE_MENU; - - inputState.mouseReadAbs(&m_prevmousepos); - m_mouselastactivity = -M_MOUSETIMEOUT; - -#if !defined EDUKE32_TOUCH_DEVICES - m_mousewake_watchpoint = 0; -#endif - - mouseLockToWindow(0); -} - -void Menu_Close(uint8_t playerID) -{ - if (g_player[playerID].ps->gm & (MODE_GAME|MODE_DEMO)) - { - // The following lines are here so that you cannot close the menu when no game is running. - g_player[playerID].ps->gm &= ~MODE_MENU; - mouseLockToWindow(1); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) - { - ready2send = 1; - totalclock = ototalclock; - CAMERACLOCK = (int32_t) totalclock; - CAMERADIST = 65536; - m_animation.start = 0; - m_animation.length = 0; - - // Reset next-viewscreen-redraw counter. - // XXX: are there any other cases like that in need of handling? - if (g_curViewscreen >= 0) - actor[g_curViewscreen].t_data[0] = (int32_t) totalclock; - } - - G_UpdateScreenArea(); - - if (!ud.pause_on) - S_PauseSounds(false); - } -} - -static int32_t x_widescreen_left(void) -{ - return (320<<15) - scale(240<<15, xdim, ydim); -} - -static int32_t xdim_from_320_16(int32_t x) -{ - const int32_t screenwidth = scale(240<<16, xdim, ydim); - return scale(x + (screenwidth>>1) - (160<<16), xdim, screenwidth); -} -static int32_t ydim_from_200_16(int32_t y) -{ - return scale(y, ydim, 200<<16); -} - -static void Menu_BlackRectangle(int32_t x, int32_t y, int32_t width, int32_t height, int32_t orientation) -{ - const int32_t xscale = divscale16(width, tilesiz[0].x<<16), yscale = divscale16(height, tilesiz[0].y<<16); - - rotatesprite_(x, y, max(xscale, yscale), 0, 0, 127, ud.shadow_pal, (orientation&(1|32))|2|8|16, 0, 0, xdim_from_320_16(x), ydim_from_200_16(y), xdim_from_320_16(x + width), ydim_from_200_16(y + height)); -} - -enum MenuTextFlags_t -{ - MT_Selected = 1<<0, - MT_Disabled = 1<<1, - MT_XCenter = 1<<2, - MT_XRight = 1<<3, - MT_YCenter = 1<<4, - MT_Literal = 1<<5, - MT_RightSide = 1<<6, -}; - -static void Menu_GetFmt(const MenuFont_t *font, uint8_t const status, int32_t *s) -{ - if (status & MT_Selected) - *s = sintable[((int32_t) totalclock<<5)&2047]>>12; - else - *s = font->shade_deselected; - // sum shade values - if (status & MT_Disabled) - *s += font->shade_disabled; -} - -static vec2_t Menu_Text(int32_t x, int32_t y, const MenuFont_t *font, const char *t, uint8_t status, int32_t ydim_upper, int32_t ydim_lower) -{ - int32_t s, p, ybetween = font->between.y; - int32_t f = font->textflags | TEXT_RRMENUTEXTHACK; - if (status & MT_XCenter) - f |= TEXT_XCENTER; - if (status & MT_XRight) - f |= TEXT_XRIGHT; - if (status & MT_YCenter) - { - f |= TEXT_YCENTER | TEXT_YOFFSETZERO; - ybetween = font->emptychar.y; // <^ the battle against 'Q' - } - if (status & MT_Literal) - f |= TEXT_LITERALESCAPE; - - int32_t z = font->zoom; - - if (status & MT_Disabled) - p = (status & MT_RightSide) ? font->pal_disabled_right : font->pal_disabled; - else if (status & MT_Selected) - p = (status & MT_RightSide) ? font->pal_selected_right : font->pal_selected; - else - p = (status & MT_RightSide) ? font->pal_deselected_right : font->pal_deselected; - - Menu_GetFmt(font, status, &s); - - return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2|8|16|ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim-1, ydim_lower); -} - -#if 0 -static vec2_t Menu_TextSize(int32_t x, int32_t y, const MenuFont_t *font, const char *t, uint8_t status) -{ - int32_t f = font->textflags; - if (status & MT_Literal) - f |= TEXT_LITERALESCAPE; - - return G_ScreenTextSize(font->tilenum, x, y, font->zoom, 0, t, 2|8|16|ROTATESPRITE_FULL16, font->emptychar.x, font->emptychar.y, font->between.x, font->between.y, f, 0, 0, xdim-1, ydim-1); -} -#endif - -static int32_t Menu_FindOptionBinarySearch(MenuOption_t *object, const int32_t query, uint16_t searchstart, uint16_t searchend) -{ - const uint16_t thissearch = (searchstart + searchend) / 2; - const bool isIdentityMap = object->options->optionValues == NULL; - const int32_t destination = isIdentityMap ? (int32_t)thissearch : object->options->optionValues[thissearch]; - const int32_t difference = query - destination; - - Bassert(!isIdentityMap || query >= 0); - - if (difference == 0) - return thissearch; - else if (searchstart == searchend) - return -1; - else if (difference > 0) - { - if (thissearch == searchend) - return -1; - searchstart = thissearch + 1; - } - else if (difference < 0) - { - if (thissearch == searchstart) - return -1; - searchend = thissearch - 1; - } - - return Menu_FindOptionBinarySearch(object, query, searchstart, searchend); -} - -static int32_t Menu_MouseOutsideBounds(vec2_t const * const pos, const int32_t x, const int32_t y, const int32_t width, const int32_t height) -{ - return pos->x < x || pos->x >= x + width || pos->y < y || pos->y >= y + height; -} - -static void Menu_RunScrollbar(Menu_t *cm, MenuMenuFormat_t const * const format, const int32_t totalextent, int32_t * const scrollPos, const int32_t rightedge, const vec2_t origin) -{ - if (totalextent > klabs(format->bottomcutoff)) - { - int32_t scrollTile = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum : -1; - int32_t scrollTileTop = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 1 : -1; - int32_t scrollTileBottom = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 2 : -1; - int32_t scrollTileCursor = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 3 : SELECTDIR; - - const int32_t scrollwidth = (scrollTile >= 0) ? tilesiz[scrollTile].x*ud.menu_scrollbarz : tilesiz[scrollTileCursor].x*ud.menu_scrollcursorz; - const int32_t scrollx = origin.x + rightedge - scrollwidth, scrolly = origin.y + format->pos.y; - const int32_t scrollheight = klabs(format->bottomcutoff) - format->pos.y; - int32_t scrollregionstart = scrolly; - int32_t scrollregionend = scrolly + scrollheight; - if (ud.menu_scrollbartilenum >= 0) - { - scrollregionstart += tilesiz[scrollTileTop].y*ud.menu_scrollbarz; - scrollregionend -= tilesiz[scrollTileBottom].y*ud.menu_scrollbarz; - } - const int32_t scrollregionheight = scrollregionend - scrollregionstart - (tilesiz[scrollTileCursor].y*ud.menu_scrollcursorz); - const int32_t scrollPosMax = totalextent - klabs(format->bottomcutoff); - - if (scrollTile >= 0) - { - // draw the scrollbar (minus the top tile) twice to fill the gaps between tiles - if (tilesiz[scrollTile].y > 0) - { - for (int32_t y = scrollregionstart + ((tilesiz[scrollTileTop].y == 0)*tilesiz[scrollTile].y*ud.menu_scrollbarz); y < scrollregionend; y += tilesiz[scrollTile].y*ud.menu_scrollbarz) - rotatesprite(scrollx, y - (ud.menu_scrollbarz>>1), ud.menu_scrollbarz, 0, scrollTile, 0, 0, 26, 0, 0, xdim-1, mulscale16(scrollregionend, ydim*200)-1); - } - rotatesprite_fs(scrollx, scrollregionend - (ud.menu_scrollbarz>>1), ud.menu_scrollbarz, 0, scrollTileBottom, 0, 0, 26); - - if (tilesiz[scrollTile].y > 0) - { - for (int32_t y = scrollregionstart; y < scrollregionend; y += tilesiz[scrollTile].y*ud.menu_scrollbarz) - rotatesprite(scrollx, y, ud.menu_scrollbarz, 0, scrollTile, 0, 0, 26, 0, 0, xdim-1, mulscale16(scrollregionend, ydim*200)-1); - } - rotatesprite_fs(scrollx, scrolly, ud.menu_scrollbarz, 0, scrollTileTop, 0, 0, 26); - rotatesprite_fs(scrollx, scrollregionend, ud.menu_scrollbarz, 0, scrollTileBottom, 0, 0, 26); - } - else - Menu_BlackRectangle(scrollx, scrolly, scrollwidth, scrollheight, 1|32); - - rotatesprite_fs(scrollx + (scrollwidth>>1) - ((tilesiz[scrollTileCursor].x*ud.menu_scrollcursorz)>>1), scrollregionstart + scale(scrollregionheight, *scrollPos, scrollPosMax), ud.menu_scrollcursorz, 0, scrollTileCursor, 0, 0, 26); - - if (cm == m_currentMenu && !m_mousecaught && MOUSEACTIVECONDITIONAL(inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - const int32_t scrolltilehalfheight = (tilesiz[scrollTileCursor].y*ud.menu_scrollcursorz)>>1; - const int32_t scrollregiony = scrollregionstart + scrolltilehalfheight; - - // region between the y-midline of the arrow at the extremes scrolls proportionally - if (!Menu_MouseOutsideBounds(&m_mousepos, scrollx, scrollregiony, scrollwidth, scrollregionheight)) - { - *scrollPos = scale(m_mousepos.y - scrollregiony, scrollPosMax, scrollregionheight); - - m_mousecaught = 1; - } - // region outside the y-midlines clamps to the extremes - else if (!Menu_MouseOutsideBounds(&m_mousepos, scrollx, scrolly, scrollwidth, scrollheight)) - { - if (m_mousepos.y > scrolly + scrollheight/2) - *scrollPos = scrollPosMax; - else - *scrollPos = 0; - - m_mousecaught = 1; - } - } - } -} - -typedef enum MenuMovement_t -{ - MM_Up = 1, - MM_End = 3, - MM_Down = 4, - MM_Home = 12, - MM_Left = 16, - MM_AllTheWayLeft = 48, - MM_Right = 64, - MM_AllTheWayRight = 192, - MM_Swap = 80, -} MenuMovement_t; - -static MenuEntry_t *Menu_RunInput_Menu_MovementVerify(MenuMenu_t *menu); -static MenuEntry_t *Menu_RunInput_Menu_Movement(MenuMenu_t *menu, MenuMovement_t direction); -static void Menu_RunInput_EntryLink_Activate(MenuEntry_t *entry); -static void Menu_RunInput_EntryOptionList_MovementVerify(MenuOption_t *object); -static void Menu_RunInput_EntryOptionList_Movement(MenuOption_t *object, MenuMovement_t direction); -static int32_t Menu_RunInput_EntryOption_Modify(MenuEntry_t *entry, MenuOption_t *object, int32_t newValueIndex); -static int32_t Menu_RunInput_EntryOption_Movement(MenuEntry_t *entry, MenuOption_t *object, MenuMovement_t direction); -static int32_t Menu_RunInput_EntryOption_Activate(MenuEntry_t *entry, MenuOption_t *object); -static int32_t Menu_RunInput_EntryOptionList_Activate(MenuEntry_t *entry, MenuOption_t *object); -static void Menu_RunInput_EntryCustom2Col_Activate(MenuEntry_t *entry); -static void Menu_RunInput_EntryRangeInt32_MovementVerify(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue); -static void Menu_RunInput_EntryRangeInt32_MovementArbitrary(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue); -static void Menu_RunInput_EntryRangeInt32_Movement(MenuEntry_t *entry, MenuRangeInt32_t *object, MenuMovement_t direction); -static void Menu_RunInput_EntryRangeFloat_MovementVerify(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue); -static void Menu_RunInput_EntryRangeFloat_MovementArbitrary(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue); -static void Menu_RunInput_EntryRangeFloat_Movement(MenuEntry_t *entry, MenuRangeFloat_t *object, MenuMovement_t direction); -#ifdef MENU_ENABLE_RANGEDOUBLE -static void Menu_RunInput_EntryRangeDouble_MovementVerify(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue); -static void Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue); -static void Menu_RunInput_EntryRangeDouble_Movement(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, MenuMovement_t direction); -#endif -static void Menu_RunInput_EntryString_Activate(MenuEntry_t *entry); -static void Menu_RunInput_EntryString_Submit(/*MenuEntry_t *entry, */MenuString_t *object); -static void Menu_RunInput_EntryString_Cancel(/*MenuEntry_t *entry, */MenuString_t *object); -static void Menu_RunInput_FileSelect_MovementVerify(MenuFileSelect_t *object); -static void Menu_RunInput_FileSelect_Movement(MenuFileSelect_t *object, MenuMovement_t direction); -static void Menu_RunInput_FileSelect_Select(MenuFileSelect_t *object); - -static int32_t M_RunMenu_Menu(Menu_t *cm, MenuMenu_t *menu, MenuEntry_t *currentry, int32_t state, const vec2_t origin, bool actually_draw) -{ - int32_t totalHeight = 0; - - // RIP MenuGroup_t b. 2014-03-?? d. 2014-11-29 - { - int32_t e; - const int32_t y_upper = menu->format->pos.y; - const int32_t y_lower = klabs(menu->format->bottomcutoff); - int32_t y = 0; - int32_t calculatedentryspacing = 0; - - if (menu->format->bottomcutoff < 0) - { - int32_t totalheight = 0, numvalidentries = 0; - - for (e = 0; e < menu->numEntries; ++e) - { - MenuEntry_t *entry = menu->entrylist[e]; - - if (entry == NULL || (entry->flags & MEF_Hidden)) - continue; - - ++numvalidentries; - - // assumes height == font->get_yline()! - totalheight += entry->getHeight(); - } - - calculatedentryspacing = (klabs(menu->format->bottomcutoff) - menu->format->pos.y - totalheight) / (numvalidentries > 1 ? numvalidentries - 1 : 1); - } - - // totalHeight calculating pass - for (e = 0; e < menu->numEntries; ++e) - { - MenuEntry_t *entry = menu->entrylist[e]; - - if (entry == NULL || (entry->flags & MEF_Hidden)) - continue; - - int32_t const height = entry->getHeight(); - - y += height; - totalHeight = y; - y += (!calculatedentryspacing || calculatedentryspacing > entry->getMarginBottom()) ? entry->getMarginBottom() : calculatedentryspacing; - } - y = 0; - - int32_t ydim_upper, ydim_lower; - if (y_upper + totalHeight > y_lower) - { - ydim_upper = ydim_from_200_16(origin.y + y_upper); - ydim_lower = ydim_from_200_16(origin.y + y_lower); - } - else - { - ydim_upper = 0; - ydim_lower = ydim-1; - } - - for (e = 0; e < menu->numEntries; ++e) - { - MenuEntry_t *entry = menu->entrylist[e]; - - if (entry == NULL || (entry->flags & MEF_Hidden)) - continue; - - int32_t const indent = entry->getIndent(); - int32_t x = menu->format->pos.x; - - uint8_t status = 0; - if (e == menu->currentEntry) - status |= MT_Selected; - if (entry->flags & (MEF_Disabled|MEF_LookDisabled)) - status |= MT_Disabled; - if (entry->format->width == 0) - status |= MT_XCenter; - - bool const dodraw = entry->type != Spacer && actually_draw && - 0 <= y - menu->scrollPos + entry->font->get_yline() && - y - menu->scrollPos <= klabs(menu->format->bottomcutoff) - menu->format->pos.y; - - int32_t const height = entry->getHeight(); // max(textsize.y, entry->font->get_yline()); // bluefont Q ruins this - status |= MT_YCenter; - int32_t const y_internal = origin.y + y_upper + y + (height>>1) - menu->scrollPos; - - vec2_t textsize; - if (dodraw) - textsize = Menu_Text(origin.x + x + indent, y_internal, entry->font, entry->name, status, ydim_upper, ydim_lower); - - if (entry->format->width < 0) - status |= MT_XRight; - - if (dodraw && (status & MT_Selected) && state != 1) - { - if (status & MT_XCenter) - { - Menu_DrawCursorLeft(origin.x + (MENU_MARGIN_CENTER<<16) + entry->font->cursorCenterPosition, y_internal, entry->font->cursorScale); - Menu_DrawCursorRight(origin.x + (MENU_MARGIN_CENTER<<16) - entry->font->cursorCenterPosition, y_internal, entry->font->cursorScale); - } - else - Menu_DrawCursorLeft(origin.x + x + indent - entry->font->cursorLeftPosition, y_internal, entry->font->cursorScale2); - } - - if (entry->name != nullptr && entry->name[0] != '\0') - status |= MT_RightSide; - - // need this up here to avoid race conditions - entry->ybottom = (entry->ytop = y_upper + y) + height; - - if (dodraw) - { - const int32_t mousex = origin.x + indent + entry->format->width == 0 ? x - textsize.x/2 : x; - const int32_t mousey = origin.y + y_upper + y - menu->scrollPos; - int32_t mousewidth = entry->format->width == 0 ? textsize.x : klabs(entry->format->width); - - if (entry->name) - x += klabs(entry->format->width); - - switch (entry->type) - { - case Spacer: - break; - case Dummy: - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - } - break; - case Link: - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, entry->font->get_yline())) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryLink_Activate(entry); - - if (g_player[myconnectindex].ps->gm&MODE_MENU) // for skill selection - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - break; - case Option: - { - auto *object = (MenuOption_t*)entry->entry; - int32_t currentOption = Menu_FindOptionBinarySearch(object, object->cVar == NULL ? Menu_EntryOptionSource(entry, object->currentOption) : object->cVar->ToInt(), 0, object->options->numOptions); - - if (currentOption >= 0) - object->currentOption = currentOption; - - int32_t optiontextx = origin.x + x; - const int32_t optiontexty = origin.y + y_upper + y - menu->scrollPos; - - const vec2_t optiontextsize = Menu_Text(optiontextx, optiontexty + (height>>1), object->font, - currentOption < 0 ? MenuCustom : currentOption < object->options->numOptions ? object->options->optionNames[currentOption] : NULL, - status, ydim_upper, ydim_lower); - - if (entry->format->width > 0) - mousewidth += optiontextsize.x; - else - optiontextx -= optiontextsize.x; - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, entry->font->get_yline())) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryOption_Activate(entry, object); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - - break; - } - case Custom2Col: - { - auto *object = (MenuCustom2Col_t*)entry->entry; - int32_t columnx[2] = { origin.x + x - ((status & MT_XRight) ? object->columnWidth : 0), origin.x + x + ((status & MT_XRight) ? 0 : object->columnWidth) }; - const int32_t columny = origin.y + y_upper + y - menu->scrollPos; - - const vec2_t column0textsize = Menu_Text(columnx[0], columny + (height>>1), object->font, object->key[*object->column[0]], menu->currentColumn == 0 ? status : (status & ~MT_Selected), ydim_upper, ydim_lower); - const vec2_t column1textsize = Menu_Text(columnx[1], columny + (height>>1), object->font, object->key[*object->column[1]], menu->currentColumn == 1 ? status : (status & ~MT_Selected), ydim_upper, ydim_lower); - - if (entry->format->width > 0) - mousewidth += object->columnWidth + column1textsize.x; - else - { - columnx[0] -= column0textsize.x; - columnx[1] -= column0textsize.x; - } - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!Menu_MouseOutsideBounds(&m_mousepos, columnx[1], mousey, column1textsize.x, object->font->get_yline())) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, columnx[1], mousey, column1textsize.x, object->font->get_yline()))) - { - menu->currentColumn = 1; - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, columnx[1], mousey, column1textsize.x, object->font->get_yline())) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - menu->currentColumn = 1; - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryCustom2Col_Activate(entry); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - else if (!Menu_MouseOutsideBounds(&m_mousepos, columnx[0], mousey, column0textsize.x, object->font->get_yline())) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, columnx[0], mousey, column0textsize.x, object->font->get_yline()))) - { - menu->currentColumn = 0; - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, columnx[0], mousey, column0textsize.x, object->font->get_yline())) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - menu->currentColumn = 0; - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryCustom2Col_Activate(entry); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - } - break; - } - case RangeInt32: - { - auto *object = (MenuRangeInt32_t*)entry->entry; - - int32_t s, p; - int32_t z = entry->font->cursorScale3; - Menu_GetFmt(object->font, status|MT_RightSide, &s); - - if (status & MT_Disabled) - p = ud.slidebar_paldisabled; - else if (status & MT_Selected) - p = ud.slidebar_palselected; - else - p = 0; - - const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z); - const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z); - - if (status & MT_XRight) - x -= slidebarwidth; - else - mousewidth += slidebarwidth; - - const int32_t slidebarx = origin.x + x; - const int32_t slidebary = origin.y + y_upper + y + ((height - slidebarheight)>>1) - menu->scrollPos; - - rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - const int32_t cursorTile = RR ? BIGALPHANUM-9 : SLIDEBAR+1; - const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[cursorTile].x * ud.menu_slidecursorz), z); - const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + scale(slideregionwidth, *object->cVar - object->min, object->max - object->min); - const int32_t slidepointy = slidebary + mulscale16(((tilesiz[SLIDEBAR].y * ud.menu_slidebarz) - (tilesiz[cursorTile].y * ud.menu_slidecursorz))>>1, z); - - rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, cursorTile, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - if (object->flags & DisplayTypeMask) - { - status |= MT_XRight; - - int32_t onehundredpercent = object->onehundredpercent; - if (onehundredpercent == 0) - onehundredpercent = object->max; - - switch (object->flags & DisplayTypeMask) - { - case DisplayTypeInteger: - Bsprintf(tempbuf, "%d", **object->cVar); - break; - case DisplayTypePercent: - Bsprintf(tempbuf, "%d%%", roundscale(*object->cVar, 100, onehundredpercent)); - break; - case DisplayTypeNormalizedDecimal: - Bsprintf(tempbuf, "%.2f", (double) *object->cVar / (double) onehundredpercent); - break; - } - - Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + (height>>1) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower); - } - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - const int32_t slidepointhalfwidth = mulscale16((((tilesiz[cursorTile].x)*ud.menu_slidecursorz)>>2) + ud.menu_slidebarmargin, z); - const int32_t slideregionx = slidebarx + slidepointhalfwidth; - - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - // region between the x-midline of the slidepoint at the extremes slides proportionally - if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height)) - { - Menu_RunInput_EntryRangeInt32_MovementArbitrary(entry, object, roundscale(object->max - object->min, m_mousepos.x - slideregionx, slideregionwidth) + object->min); - - m_mousecaught = 1; - } - // region outside the x-midlines clamps to the extremes - else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height)) - { - if (m_mousepos.x > slideregionx + slideregionwidth/2) - Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, object->max); - else - Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, object->min); - - m_mousecaught = 1; - } - } - } - - break; - } - case RangeFloat: - { - auto *object = (MenuRangeFloat_t*)entry->entry; - - int32_t s, p; - int32_t z = entry->font->cursorScale3; - Menu_GetFmt(object->font, status|MT_RightSide, &s); - - if (status & MT_Disabled) - p = ud.slidebar_paldisabled; - else if (status & MT_Selected) - p = ud.slidebar_palselected; - else - p = 0; - - const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z); - const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z); - - if (status & MT_XRight) - x -= slidebarwidth; - else - mousewidth += slidebarwidth; - - const int32_t slidebarx = origin.x + x; - const int32_t slidebary = origin.y + y_upper + y + ((height - slidebarheight)>>1) - menu->scrollPos; - - rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - const int32_t cursorTile = RR ? BIGALPHANUM-9 : SLIDEBAR+1; - const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[cursorTile].x * ud.menu_slidecursorz), z); - const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + Blrintf((float) slideregionwidth * (*object->cVar - object->min) / (object->max - object->min)); - const int32_t slidepointy = slidebary + mulscale16(((tilesiz[SLIDEBAR].y * ud.menu_slidebarz) - (tilesiz[cursorTile].y * ud.menu_slidecursorz))>>1, z); - - rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, cursorTile, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - if (object->flags & DisplayTypeMask) - { - status |= MT_XRight; - - float onehundredpercent = object->onehundredpercent; - if (onehundredpercent == 0.f) - onehundredpercent = 1.f; - - switch (object->flags & DisplayTypeMask) - { - case DisplayTypeInteger: - Bsprintf(tempbuf, "%.2f", **object->cVar); - break; - case DisplayTypePercent: - Bsprintf(tempbuf, "%ld%%", lrintf(*object->cVar * 100.f / onehundredpercent)); - break; - case DisplayTypeNormalizedDecimal: - Bsprintf(tempbuf, "%.2f", *object->cVar / onehundredpercent); - break; - } - - Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + (height>>1) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower); - } - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - const int32_t slidepointhalfwidth = mulscale16((2+tilesiz[cursorTile].x)<<15, z); - const int32_t slideregionx = slidebarx + slidepointhalfwidth; - - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - // region between the x-midline of the slidepoint at the extremes slides proportionally - if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height)) - { - Menu_RunInput_EntryRangeFloat_MovementArbitrary(entry, object, (object->max - object->min) * (m_mousepos.x - slideregionx) / slideregionwidth + object->min); - - m_mousecaught = 1; - } - // region outside the x-midlines clamps to the extremes - else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height)) - { - if (m_mousepos.x > slideregionx + slideregionwidth/2) - Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, object->max); - else - Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, object->min); - - m_mousecaught = 1; - } - } - } - - break; - } -#ifdef MENU_ENABLE_RANGEDOUBLE - case RangeDouble: - { - MenuRangeDouble_t *object = (MenuRangeDouble_t*)entry->entry; - - int32_t s, p; - int32_t z = entry->font->cursorScale3; - Menu_GetFmt(object->font, status|MT_RightSide, &s); - - if (status & MT_Disabled) - p = ud.slidebar_paldisabled; - else if (status & MT_Selected) - p = ud.slidebar_palselected; - else - p = 0; - - const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z); - const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z); - - if (status & MT_XRight) - x -= slidebarwidth; - else - mousewidth += slidebarwidth; - - const int32_t slidebarx = origin.x + x; - const int32_t slidebary = origin.y + y_upper + y + ((height - slidebarheight)>>1) - menu->scrollPos; - - rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - const int32_t cursorTile = RR ? BIGALPHANUM-9 : SLIDEBAR+1; - const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[cursorTile].x * ud.menu_slidecursorz), z); - const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + lrint((double) slideregionwidth * (*object->variable - object->min) / (object->max - object->min)); - const int32_t slidepointy = slidebary + mulscale16(((tilesiz[SLIDEBAR].y * ud.menu_slidebarz) - (tilesiz[cursorTile].y * ud.menu_slidecursorz))>>1, z); - - rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, cursorTile, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower); - - if (object->flags & DisplayTypeMask) - { - status |= MT_XRight; - - double onehundredpercent = object->onehundredpercent; - if (onehundredpercent == 0.) - onehundredpercent = 1.; - - switch (object->flags & DisplayTypeMask) - { - case DisplayTypeInteger: - Bsprintf(tempbuf, "%.2f", *object->variable); - break; - case DisplayTypePercent: - Bsprintf(tempbuf, "%ld%%", lrint(*object->variable * 100. / onehundredpercent)); - break; - case DisplayTypeNormalizedDecimal: - Bsprintf(tempbuf, "%.2f", *object->variable / onehundredpercent); - break; - } - - Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + (height>>1) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower); - } - - if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD)) - { - const int32_t slidepointhalfwidth = mulscale16((2+tilesiz[cursorTile].x)<<15, z); - const int32_t slideregionx = slidebarx + slidepointhalfwidth; - - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - // region between the x-midline of the slidepoint at the extremes slides proportionally - if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height)) - { - Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*entry, */object, (object->max - object->min) * (m_mousepos.x - slideregionx) / slideregionwidth + object->min); - - m_mousecaught = 1; - } - // region outside the x-midlines clamps to the extremes - else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height)) - { - if (m_mousepos.x > slideregionx + slideregionwidth/2) - Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, object->max); - else - Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, object->min); - - m_mousecaught = 1; - } - } - } - - break; - } -#endif - case String: - { - auto *object = (MenuString_t*)entry->entry; - - vec2_t dim; - int32_t stringx = x; - const int32_t stringy = origin.y + y_upper + y + (height>>1) - menu->scrollPos; - int32_t h; - - if (entry == currentry && object->editfield != NULL) - { - dim = Menu_Text(origin.x + stringx, stringy, object->font, object->editfield, (status & ~MT_Disabled) | MT_Literal, ydim_upper, ydim_lower); - h = max(dim.y, entry->font->get_yline()); - - Menu_DrawCursorText(origin.x + x + dim.x + (1<<16), stringy, h, ydim_upper, ydim_lower); - } - else - { - dim = Menu_Text(origin.x + stringx, stringy, object->font, object->variable, status, ydim_upper, ydim_lower); - h = max(dim.y, entry->font->get_yline()); - } - - if (entry->format->width > 0) - { - if (entry->name) - mousewidth += dim.x; - } - else - stringx -= dim.x; - - if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, h))) - { - if (state != 1 && Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, h)) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - } - - #ifndef EDUKE32_TOUCH_DEVICES - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, h) && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, h)) - #endif - { - if (entry == currentry && object->editfield != NULL) - { - Menu_RunInput_EntryString_Submit(/*entry, */object); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - m_mousecaught = 1; - } - else if (state != 1) - { - menu->currentEntry = e; - Menu_RunInput_Menu_MovementVerify(menu); - - if (entry->flags & MEF_Disabled) - break; - - Menu_RunInput_EntryString_Activate(entry); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - } - - break; - } - } - } - - // prepare for the next line - y += height; - y += (!calculatedentryspacing || calculatedentryspacing > entry->getMarginBottom()) ? entry->getMarginBottom() : calculatedentryspacing; - } - - // draw indicators if applicable - if (actually_draw) - Menu_RunScrollbar(cm, menu->format, y_upper + totalHeight, &menu->scrollPos, 320<<16, origin); - } - - return totalHeight; -} - -static void M_RunMenu_CdPlayer(Menu_t *cm, MenuMenu_t *menu, const vec2_t origin) -{ - static const vec2_t entryPos[8] = { - { 22, 15 }, { 64, 15 }, { 104, 15 }, { 142, 15 }, - { 22, 25 }, { 64, 25 }, { 104, 25 }, { 142, 25 }, - }; - - // RIP MenuGroup_t b. 2014-03-?? d. 2014-11-29 - { - int32_t e; - - for (e = 0; e < menu->numEntries; ++e) - { - const int32_t x = entryPos[e].x-154+(MENU_MARGIN_CENTER<<1); - const int32_t y = entryPos[e].y+65; - - const int32_t mousex = origin.x+(x<<15)-(4<<16); - const int32_t mousey = origin.y+(y<<16)-(4<<16); - - if (e == menu->currentEntry && mus_enabled) - rotatesprite_fs(origin.x+(x<<15), origin.y+(y<<16), 32768, 0, CDPLAYER+1, 16, 0, 10); - - - if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, 8<<16, 8<<16))) - { - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED) - { - menu->currentEntry = e; - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - - m_mousecaught = 1; - } - } - //switch (entry->type) - //{ - // case Spacer: - // break; - // case Dummy: - //if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height))) - //{ - // if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height))) - // { - // menu->currentEntry = e; - // Menu_RunInput_Menu_MovementVerify(menu); - // } - //} - //break; - //} - } - } - - const int32_t mousex = origin.x+((MENU_MARGIN_CENTER-60)<<16)-(8<<16); - const int32_t mousey = origin.y+(113<<16)-(8<<16); - if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, 16<<16, 16<<16))) - { - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED) - { - mus_enabled = !mus_enabled; - - if (mus_enabled == 0) - S_PauseMusic(true); - else - { - S_PlayRRMusic(2+menu->currentEntry); - S_PauseMusic(false); - } - - m_mousecaught = 1; - } - } - - if (mus_enabled) - rotatesprite_fs(origin.x+((MENU_MARGIN_CENTER-60)<<16), origin.y+(113<<16), 32768, 0, CDPLAYER+3, 16, 0, 10); - else - rotatesprite_fs(origin.x+((MENU_MARGIN_CENTER-60)<<16), origin.y+(113<<16), 32768, 0, CDPLAYER+2, 16, 0, 10); - - return; -} - -static void Menu_RunOptionList(Menu_t *cm, MenuEntry_t *entry, MenuOption_t *object, const vec2_t origin) -{ - int32_t e, y = 0; - const int32_t y_upper = object->options->menuFormat->pos.y; - const int32_t y_lower = object->options->menuFormat->bottomcutoff; - int32_t calculatedentryspacing = object->options->getMarginBottom(); - - // assumes height == font->get_yline()! - if (calculatedentryspacing < 0) - calculatedentryspacing = (-calculatedentryspacing - object->options->font->get_yline()) / (object->options->numOptions - 1) - object->options->font->get_yline(); - - int32_t totalHeight = 0; - for (e = 0; e < object->options->numOptions; ++e) - { - int32_t const height = object->options->font->get_yline(); - - y += height; - totalHeight = y; - y += calculatedentryspacing; - } - y = 0; - - int32_t ydim_upper, ydim_lower; - if (y_upper + totalHeight > y_lower) - { - ydim_upper = ydim_from_200_16(origin.y + y_upper); - ydim_lower = ydim_from_200_16(origin.y + y_lower); - } - else - { - ydim_upper = 0; - ydim_lower = ydim-1; - } - - for (e = 0; e < object->options->numOptions; ++e) - { - int32_t const x = object->options->menuFormat->pos.x; - - uint8_t status = 0; - if (e == object->options->currentEntry) - status |= MT_Selected; - if (object->options->entryFormat->width == 0) - status |= MT_XCenter; - - bool const dodraw = 0 <= y - object->options->scrollPos + object->options->font->get_yline() && - y - object->options->scrollPos <= object->options->menuFormat->bottomcutoff - object->options->menuFormat->pos.y; - - int32_t const height = object->options->font->get_yline(); // max(textsize.y, object->options->font->get_yline()); - status |= MT_YCenter; - int32_t const y_internal = origin.y + y_upper + y + (height>>1) - object->options->scrollPos; - - vec2_t textsize; - if (dodraw) - textsize = Menu_Text(origin.x + x, y_internal, object->options->font, object->options->optionNames[e], status, ydim_upper, ydim_lower); - - if (object->options->entryFormat->width < 0) - status |= MT_XRight; - - if (dodraw && (status & MT_Selected)) - { - if (status & MT_XCenter) - { - Menu_DrawCursorLeft(origin.x + (MENU_MARGIN_CENTER<<16) + object->options->font->cursorCenterPosition, y_internal, object->options->font->cursorScale); - Menu_DrawCursorRight(origin.x + (MENU_MARGIN_CENTER<<16) - object->options->font->cursorCenterPosition, y_internal, object->options->font->cursorScale); - } - else - Menu_DrawCursorLeft(origin.x + x - object->options->font->cursorLeftPosition, y_internal, object->options->font->cursorScale2); - } - - if (dodraw) - { - const int32_t mousex = origin.x + object->options->entryFormat->width == 0 ? x - textsize.x/2 : x; - const int32_t mousey = origin.y + y_upper + y - object->options->scrollPos; - const int32_t mousewidth = object->options->entryFormat->width == 0 ? textsize.x : klabs(object->options->entryFormat->width); - - if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, object->options->font->get_yline()))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, object->options->font->get_yline()))) - { - object->options->currentEntry = e; - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, object->options->font->get_yline())) - { - object->options->currentEntry = e; - - if (!Menu_RunInput_EntryOptionList_Activate(entry, object)) - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - m_mousecaught = 1; - } - } - } - - // prepare for the next line - y += height; - y += calculatedentryspacing; - } - - // draw indicators if applicable - Menu_RunScrollbar(cm, object->options->menuFormat, y_upper + totalHeight, &object->options->scrollPos, 320<<16, origin); -} - -static int32_t Menu_RunInput_MouseAdvance(void) -{ - return MOUSEACTIVECONDITIONAL(!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED); -} - -static int32_t Menu_RunInput_MouseReturn_status; - -#if !defined EDUKE32_TOUCH_DEVICES -static void Menu_Run_MouseReturn(Menu_t *cm, const vec2_t origin) -{ - if (!MOUSEACTIVECONDITION) - return; - - if (cm->menuID == MENU_MAIN) - return; - - uint32_t const posx = tilesiz[SELECTDIR].y * SELECTDIR_z; - - rotatesprite_(origin.x + posx, 0, SELECTDIR_z, 512, SELECTDIR, - Menu_RunInput_MouseReturn_status ? 4 - (sintable[((int32_t) totalclock << 4) & 2047] >> 11) : 6, 0, - 2 | 8 | 16 | RS_ALIGN_L, MOUSEALPHA, 0, xdim_from_320_16(origin.x + x_widescreen_left()), 0, - xdim_from_320_16(origin.x + x_widescreen_left() + (posx>>1)), ydim - 1); -} -#endif - -static int32_t Menu_RunInput_MouseReturn(void) -{ -#if !defined EDUKE32_TOUCH_DEVICES - if (!MOUSEACTIVECONDITION) - { - Menu_RunInput_MouseReturn_status = 0; - return 0; - } -#endif - - if (g_currentMenu == MENU_MAIN) - return 0; - - const int32_t MouseReturnRegionX = x_widescreen_left(); - - vec2_t backbuttonbound = { (tilesiz[SELECTDIR].y * SELECTDIR_z)>>1, tilesiz[SELECTDIR].x * SELECTDIR_z }; - - if (!Menu_MouseOutsideBounds(&m_mousepos, MouseReturnRegionX, 0, backbuttonbound.x, backbuttonbound.y)) - { -#if !defined EDUKE32_TOUCH_DEVICES - Menu_RunInput_MouseReturn_status = 1; -#else - Menu_RunInput_MouseReturn_status = (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD); -#endif - - return !m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, MouseReturnRegionX, 0, backbuttonbound.x, backbuttonbound.y); - } - - Menu_RunInput_MouseReturn_status = 0; - - return 0; -} - -static void Menu_Run_AbbreviateNameIntoBuffer(const char* name, int32_t entrylength) -{ - int32_t len = Bstrlen(name); - Bstrncpy(tempbuf, name, ARRAY_SIZE(tempbuf)); - if (len > entrylength) - { - len = entrylength-3; - tempbuf[len] = 0; - while (len < entrylength) - tempbuf[len++] = '.'; - } - tempbuf[len] = 0; -} - -static void Menu_Recurse(MenuID_t cm, const vec2_t origin) -{ - switch (cm) - { - case MENU_SAVECLEANVERIFY: - case MENU_LOADVERIFY: - case MENU_LOADDELVERIFY: - case MENU_SAVEVERIFY: - case MENU_SAVEDELVERIFY: - case MENU_ADULTPASSWORD: - case MENU_CHEATENTRY: - case MENU_CHEAT_WARP: - case MENU_CHEAT_SKILL: - Menu_Run(m_previousMenu, origin); - break; - default: - break; - } -} - -static void Menu_Run(Menu_t *cm, const vec2_t origin) -{ - Menu_Recurse(cm->menuID, origin); - - switch (cm->type) - { - case Verify: - { - auto *object = (MenuVerify_t*)cm->object; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - Menu_PreDraw(cm->menuID, NULL, origin); - - Menu_DrawCursorLeft(origin.x + object->cursorpos.x, origin.y + object->cursorpos.y, RR ? 3276 : 65536); - - break; - } - - case Message: - { - auto *object = (MenuMessage_t*)cm->object; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - Menu_PreDraw(cm->menuID, NULL, origin); - - Menu_DrawCursorLeft(origin.x + object->cursorpos.x, origin.y + object->cursorpos.y, RR ? 3276 : 65536); - - break; - } - - case TextForm: - { - auto *object = (MenuTextForm_t*)cm->object; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - Menu_BlackRectangle(origin.x + (60<<16), origin.y + (86<<16), 200<<16, 28<<16, 0); - - mgametextcenter(origin.x, origin.y + (98<<16), object->instructions, TEXT_YBOTTOM); - - const char *displaytext = object->input; - - if (object->flags & MTF_Password) - { - size_t x; - for (x = 0; x < Bstrlen(object->input); ++x) - tempbuf[x] = '*'; - tempbuf[x] = 0; - - displaytext = tempbuf; - } - - const vec2_t textreturn = mgametextcenter(origin.x, origin.y + (102<<16), displaytext); - - Menu_PreDraw(cm->menuID, NULL, origin); - - int32_t const h = MF_Bluefont.get_yline(); - - Menu_DrawCursorText(origin.x + (MENU_MARGIN_CENTER<<16) + (textreturn.x>>1) + (1<<16), origin.y + (102<<16) + (h>>1), h); - - break; - } - - case FileSelect: - { -#if 0 - auto *object = (MenuFileSelect_t*)cm->object; - const int32_t MenuFileSelect_scrollbar_rightedge[2] = { 160<<16, 284<<16 }; - int32_t i, selected = 0; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - if (object->title != NoTitle) - Menu_DrawTopBar(origin); - - - // black translucent background underneath file lists - Menu_BlackRectangle(origin.x + (36<<16), origin.y + (42<<16), 248<<16, 123<<16, 1|32); - - // path - Bsnprintf(tempbuf, sizeof(tempbuf), "Path: %s", object->destination); - mgametext(origin.x + object->format[0]->pos.x, origin.y + (32<<16), tempbuf); - - uint8_t column_status[2] = { 0, MT_RightSide }; - - for (i = 0; i < 2; ++i) - { - if (object->findhigh[i]) - { - CACHE1D_FIND_REC *dir; - int32_t y = 0; - const int32_t y_upper = object->format[i]->pos.y; - const int32_t y_lower = klabs(object->format[i]->bottomcutoff); - - int32_t totalHeight = 0; - for (dir = object->findhigh[i]->usera; dir; dir = dir->next) - { - y += object->font[i]->get_yline(); - totalHeight = y; - y += object->getMarginBottom(i); - } - y = 0; - - int32_t ydim_upper, ydim_lower; - if (y_upper + totalHeight > y_lower) - { - ydim_upper = ydim_from_200_16(origin.y + y_upper); - ydim_lower = ydim_from_200_16(origin.y + y_lower); - } - else - { - ydim_upper = 0; - ydim_lower = ydim-1; - } - - for (dir = object->findhigh[i]->usera; dir; dir = dir->next) - { - uint8_t status = column_status[i]; - if (dir == object->findhigh[i] && object->currentList == i) - status |= MT_Selected; - - Menu_Run_AbbreviateNameIntoBuffer(dir->name, USERMAPENTRYLENGTH); - - const int32_t thisx = object->format[i]->pos.x; - const int32_t thisy = y - object->scrollPos[i]; - - int32_t const height = object->font[i]->get_yline(); - - if (0 <= thisy + height && thisy <= klabs(object->format[i]->bottomcutoff) - object->format[i]->pos.y) - { - status |= MT_YCenter; - - const int32_t mousex = origin.x + thisx; - const int32_t mousey = origin.y + y_upper + thisy + (height>>1); - - vec2_t textdim = Menu_Text(mousex, mousey, object->font[i], tempbuf, status, ydim_upper, ydim_lower); - - if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, textdim.x, object->font[i]->get_yline()))) - { - if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, textdim.x, object->font[i]->get_yline()))) - { - object->findhigh[i] = dir; - object->currentList = i; - - Menu_RunInput_FileSelect_MovementVerify(object); - } - - if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, textdim.x, object->font[i]->get_yline())) - { - object->findhigh[i] = dir; - object->currentList = i; - - Menu_RunInput_FileSelect_MovementVerify(object); - - m_mousecaught = 1; - selected = 1; - } - } - } - - y += object->font[i]->get_yline() + object->getMarginBottom(i); - } - - Menu_RunScrollbar(cm, object->format[i], y_upper + totalHeight, &object->scrollPos[i], MenuFileSelect_scrollbar_rightedge[i], origin); - } - } - - Menu_PreDraw(cm->menuID, NULL, origin); - - if (object->title != NoTitle) - Menu_DrawTopBarCaption(object->title, origin); - - if (selected) - { - Menu_RunInput_FileSelect_Select(object); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - - m_mousecaught = 1; - } -#endif - break; - } - - case Panel: - { - auto *object = (MenuPanel_t*)cm->object; - - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - if (object->title != NoTitle) - Menu_DrawTopBar(origin); - - Menu_PreDraw(cm->menuID, NULL, origin); - - if (object->title != NoTitle) - Menu_DrawTopBarCaption(object->title, origin); - - break; - } - - case CdPlayer: - { - auto *menu = (MenuMenu_t*)cm->object; - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - if (menu->title != NoTitle) - Menu_DrawTopBar(origin); - - Menu_PreDraw(cm->menuID, NULL, origin); - - M_RunMenu_CdPlayer(cm, menu, origin); - - if (menu->title != NoTitle) - Menu_DrawTopBarCaption(menu->title, origin); - - break; - } - - case Menu: - { - int32_t state; - - auto *menu = (MenuMenu_t*)cm->object; - MenuEntry_t *currentry = menu->entrylist[menu->currentEntry]; - - state = Menu_DetermineSpecialState(currentry); - - if (state != 2) - { - Menu_Pre(cm->menuID); - - Menu_PreDrawBackground(cm->menuID, origin); - - if (menu->title != NoTitle) - Menu_DrawTopBar(origin); - - Menu_PreDraw(cm->menuID, currentry, origin); - - M_RunMenu_Menu(cm, menu, currentry, state, origin); - } - else - { - Menu_PreDrawBackground(cm->menuID, origin); - - if (menu->title != NoTitle) - Menu_DrawTopBar(origin); - - if (currentry->type == Option) - { - if (currentry->name) - Menu_DrawTopBarCaption(currentry->name, origin); - - Menu_PreOptionListDraw(currentry, origin); - - Menu_RunOptionList(cm, currentry, (MenuOption_t*)currentry->entry, origin); - } - else if (currentry->type == Custom2Col) - { - Menu_PreCustom2ColScreenDraw(currentry, origin); - } - } - - if ((currentry->type != Option || state != 2) && menu->title != NoTitle) - Menu_DrawTopBarCaption(menu->title, origin); - - break; - } - } - -#if !defined EDUKE32_TOUCH_DEVICES - Menu_Run_MouseReturn(cm, origin); -#endif -} - -/* -Note: When menus are exposed to scripting, care will need to be taken so that -a user cannot define an empty MenuEntryList, or one containing only spacers, -or else this function will recurse infinitely. -*/ -static MenuEntry_t *Menu_RunInput_Menu_MovementVerify(MenuMenu_t *menu) -{ - return Menu_AdjustForCurrentEntryAssignment(menu); -} - -static MenuEntry_t *Menu_RunInput_Menu_Movement(MenuMenu_t *menu, MenuMovement_t direction) -{ - if (menu->numEntries == 1) - return menu->entrylist[menu->currentEntry]; - - switch (direction) - { - case MM_End: - menu->currentEntry = menu->numEntries; - fallthrough__; - case MM_Up: - do - { - --menu->currentEntry; - if (menu->currentEntry < 0) - return Menu_RunInput_Menu_Movement(menu, MM_End); - } - while (!menu->entrylist[menu->currentEntry] || - (menu->entrylist[menu->currentEntry]->flags & MEF_Hidden) || - menu->entrylist[menu->currentEntry]->type == Spacer); - break; - - case MM_Home: - menu->currentEntry = -1; - fallthrough__; - case MM_Down: - do - { - ++menu->currentEntry; - if (menu->currentEntry >= menu->numEntries) - return Menu_RunInput_Menu_Movement(menu, MM_Home); - } - while (!menu->entrylist[menu->currentEntry] || - (menu->entrylist[menu->currentEntry]->flags & MEF_Hidden) || - menu->entrylist[menu->currentEntry]->type == Spacer); - break; - - case MM_Swap: - menu->currentColumn = !menu->currentColumn; - break; - - default: - break; - } - - return Menu_RunInput_Menu_MovementVerify(menu); -} - -static void Menu_RunInput_EntryLink_Activate(MenuEntry_t *entry) -{ - auto *link = (MenuLink_t*)entry->entry; - - Menu_EntryLinkActivate(entry); - - Menu_AnimateChange(link->linkID, link->animation); -} - -static void Menu_RunInput_EntryOptionList_MovementVerify(MenuOption_t *object) -{ - const int32_t listytop = object->options->menuFormat->pos.y; - // assumes height == font->get_yline()! - const int32_t unitheight = object->options->getMarginBottom() < 0 ? (-object->options->getMarginBottom() - object->options->font->get_yline()) / object->options->numOptions : (object->options->font->get_yline() + object->options->getMarginBottom()); - const int32_t ytop = listytop + object->options->currentEntry * unitheight; - const int32_t ybottom = ytop + object->options->font->get_yline(); - - if (ybottom - object->options->scrollPos > object->options->menuFormat->bottomcutoff) - object->options->scrollPos = ybottom - object->options->menuFormat->bottomcutoff; - else if (ytop - object->options->scrollPos < listytop) - object->options->scrollPos = ytop - listytop; -} - -static void Menu_RunInput_EntryOptionList_Movement(MenuOption_t *object, MenuMovement_t direction) -{ - switch (direction) - { - case MM_Up: - --object->options->currentEntry; - if (object->options->currentEntry >= 0) - break; - fallthrough__; - case MM_End: - object->options->currentEntry = object->options->numOptions-1; - break; - - case MM_Down: - ++object->options->currentEntry; - if (object->options->currentEntry < object->options->numOptions) - break; - fallthrough__; - case MM_Home: - object->options->currentEntry = 0; - break; - - default: - break; - } - - Menu_RunInput_EntryOptionList_MovementVerify(object); -} - -static int32_t Menu_RunInput_EntryOption_Modify(MenuEntry_t *entry, MenuOption_t *object, int32_t newValueIndex) -{ - int32_t newValue = (object->options->optionValues == NULL) ? newValueIndex : object->options->optionValues[newValueIndex]; - if (!Menu_EntryOptionModify(entry, newValue)) - { - object->currentOption = newValueIndex; - - if (object->cVar != NULL) // NULL implies the functions will handle it - { - UCVarValue v; - v.Int = newValue; - object->cVar->ForceSet(v, CVAR_Int, false); - } - Menu_EntryOptionDidModify(entry); - - return 0; - } - - return -1; -} - -static int32_t Menu_RunInput_EntryOption_Movement(MenuEntry_t *entry, MenuOption_t *object, MenuMovement_t direction) -{ - int32_t newValueIndex = object->currentOption; - - switch (direction) - { - case MM_Left: - --newValueIndex; - if (newValueIndex >= 0) - break; - fallthrough__; - case MM_AllTheWayRight: - newValueIndex = object->options->numOptions-1; - break; - - case MM_Right: - ++newValueIndex; - if (newValueIndex < object->options->numOptions) - break; - fallthrough__; - case MM_AllTheWayLeft: - newValueIndex = 0; - break; - - default: - break; - } - - return Menu_RunInput_EntryOption_Modify(entry, object, newValueIndex); -} - -static int32_t Menu_RunInput_EntryOption_Activate(MenuEntry_t *entry, MenuOption_t *object) -{ - if (object->options->features & 2) - return Menu_RunInput_EntryOption_Movement(entry, object, MM_Right); - else - { - object->options->currentEntry = object->currentOption >= 0 ? object->currentOption : 0; - Menu_RunInput_EntryOptionList_MovementVerify(object); - - return 0; - } -} - -static int32_t Menu_RunInput_EntryOptionList_Activate(MenuEntry_t *entry, MenuOption_t *object) -{ - if (!Menu_RunInput_EntryOption_Modify(entry, object, object->options->currentEntry)) - { - object->options->currentEntry = -1; - - return 0; - } - - return -1; -} - -static void Menu_RunInput_EntryCustom2Col_Activate(MenuEntry_t *entry) -{ - auto *object = (MenuCustom2Col_t*)entry->entry; - - Menu_Custom2ColScreen(/*entry*/); - - object->screenOpen = 1; -} - -static void Menu_RunInput_EntryRangeInt32_MovementVerify(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue) -{ - if (!Menu_EntryRangeInt32Modify(entry, newValue)) - *object->cVar = newValue; -} - -static void Menu_RunInput_EntryRangeInt32_MovementArbitrary(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue) -{ - if (object->flags & EnforceIntervals) - { - int32_t const range = object->max - object->min; - int32_t const maxInterval = object->steps - 1; - int32_t const newValueIndex = roundscale(newValue - object->min, maxInterval, range); - newValue = newValueIndex * range / maxInterval + object->min; - } - - Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, newValue); -} - -static void Menu_RunInput_EntryRangeInt32_Movement(MenuEntry_t *entry, MenuRangeInt32_t *object, MenuMovement_t direction) -{ - int32_t const oldValue = *object->cVar; - int32_t const range = object->max - object->min; - int32_t const maxInterval = object->steps - 1; - int32_t const oldValueIndex = roundscale(oldValue - object->min, maxInterval, range); - int32_t const oldValueQuantized = oldValueIndex * range / maxInterval + object->min; - int32_t newValueIndex = oldValueIndex; - - switch (direction) - { - case MM_Left: - if (oldValueQuantized >= oldValue) - --newValueIndex; - if (newValueIndex >= 0) - break; - fallthrough__; - case MM_AllTheWayLeft: - newValueIndex = 0; - break; - - case MM_Right: - if (oldValueQuantized <= oldValue) - ++newValueIndex; - if (newValueIndex <= maxInterval) - break; - fallthrough__; - case MM_AllTheWayRight: - newValueIndex = maxInterval; - break; - - default: - break; - } - - int32_t const newValue = newValueIndex * range / maxInterval + object->min; - Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, newValue); -} - -static void Menu_RunInput_EntryRangeFloat_MovementVerify(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue) -{ - if (!Menu_EntryRangeFloatModify(entry, newValue)) - { - *object->cVar = newValue; - Menu_EntryRangeFloatDidModify(entry); - } -} - -static void Menu_RunInput_EntryRangeFloat_MovementArbitrary(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue) -{ - if (object->flags & EnforceIntervals) - { - float const range = object->max - object->min; - float const maxInterval = (float)(object->steps - 1); - float const newValueIndex = rintf((newValue - object->min) * maxInterval / range); - newValue = newValueIndex * range / maxInterval + object->min; - } - - Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, newValue); -} - -static void Menu_RunInput_EntryRangeFloat_Movement(MenuEntry_t *entry, MenuRangeFloat_t *object, MenuMovement_t direction) -{ - float const oldValue = *object->cVar; - float const range = object->max - object->min; - float const maxInterval = (float)(object->steps - 1); - float const oldValueIndexUnrounded = (oldValue - object->min) * maxInterval / range; - float const oldValueIndex = rintf(oldValueIndexUnrounded); - float const oldValueQuantized = oldValueIndex * range / maxInterval + object->min; - float newValueIndex = oldValueIndex; - - switch (direction) - { - case MM_Left: - if (oldValueQuantized >= oldValue) - newValueIndex -= 1.f; - if (newValueIndex >= 0.f) - break; - fallthrough__; - case MM_AllTheWayLeft: - newValueIndex = 0.f; - break; - - case MM_Right: - if (oldValueQuantized <= oldValue) - newValueIndex += 1.f; - if (newValueIndex <= maxInterval) - break; - fallthrough__; - case MM_AllTheWayRight: - newValueIndex = maxInterval; - break; - - default: - break; - } - - float const newValue = newValueIndex * range / maxInterval + object->min; - Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, newValue); -} - -#ifdef MENU_ENABLE_RANGEDOUBLE -static void Menu_RunInput_EntryRangeDouble_MovementVerify(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue) -{ - if (!Menu_EntryRangeDoubleModify(/*entry, newValue*/)) - *object->variable = newValue; -} - -static void Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue) -{ - if (object->flags & EnforceIntervals) - { - double const range = object->max - object->min; - double const maxInterval = object->steps - 1; - double const newValueIndex = rint((newValue - object->min) * maxInterval / range); - newValue = newValueIndex * range / maxInterval + object->min; - } - - Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, newValue); -} - -static void Menu_RunInput_EntryRangeDouble_Movement(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, MenuMovement_t direction) -{ - double const oldValue = *object->variable; - double const range = object->max - object->min; - double const maxInterval = object->steps - 1; - double const oldValueIndex = rint((oldValue - object->min) * maxInterval / range); - double const oldValueQuantized = oldValueIndex * range / maxInterval + object->min; - double newValueIndex = oldValueIndex; - - switch (direction) - { - case MM_Left: - if (oldValueQuantized >= oldValue) - newValueIndex -= 1.; - if (newValueIndex >= 0.) - break; - fallthrough__; - case MM_AllTheWayLeft: - newValueIndex = 0.; - break; - - case MM_Right: - if (oldValueQuantized <= oldValue) - newValueIndex += 1.; - if (newValueIndex <= maxInterval) - break; - fallthrough__; - case MM_AllTheWayRight: - newValueIndex = maxInterval; - break; - - default: - break; - } - - double const newValue = newValueIndex * range / maxInterval + object->min; - Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, newValue); -} -#endif - -static void Menu_RunInput_EntryString_Activate(MenuEntry_t *entry) -{ - auto *object = (MenuString_t*)entry->entry; - - if (object->variable) - strncpy(typebuf, object->variable, TYPEBUFSIZE); - else - typebuf[0] = '\0'; - object->editfield = typebuf; - - // this limitation is an arbitrary implementation detail - if (object->bufsize > TYPEBUFSIZE) - object->bufsize = TYPEBUFSIZE; - - Menu_EntryStringActivate(/*entry*/); - Menu_StartTextInput(); -} - -static void Menu_RunInput_EntryString_Submit(/*MenuEntry_t *entry, */MenuString_t *object) -{ - if (!Menu_EntryStringSubmit(/*entry, */object->editfield)) - { - if (object->variable) - strncpy(object->variable, object->editfield, object->bufsize); - } - - object->editfield = NULL; - Menu_StopTextInput(); -} - -static void Menu_RunInput_EntryString_Cancel(/*MenuEntry_t *entry, */MenuString_t *object) -{ - Menu_EntryStringCancel(/*entry*/); - - object->editfield = NULL; - Menu_StopTextInput(); -} - -static void Menu_RunInput_FileSelect_MovementVerify(MenuFileSelect_t *object) -{ -#if 0 - const int32_t listytop = object->format[object->currentList]->pos.y; - const int32_t listybottom = klabs(object->format[object->currentList]->bottomcutoff); - const int32_t ytop = listytop + object->findhigh[object->currentList]->type * (object->font[object->currentList]->get_yline() + object->getMarginBottom(object->currentList)); - const int32_t ybottom = ytop + object->font[object->currentList]->get_yline(); - - if (ybottom - object->scrollPos[object->currentList] > listybottom) - object->scrollPos[object->currentList] = ybottom - listybottom; - else if (ytop - object->scrollPos[object->currentList] < listytop) - object->scrollPos[object->currentList] = ytop - listytop; -#endif -} - -static void Menu_RunInput_FileSelect_Movement(MenuFileSelect_t *object, MenuMovement_t direction) -{ -#if 0 - switch (direction) - { - case MM_Up: - if (!object->findhigh[object->currentList]) - break; - if (object->findhigh[object->currentList]->prev) - { - object->findhigh[object->currentList] = object->findhigh[object->currentList]->prev; - break; - } - fallthrough__; - case MM_End: - object->findhigh[object->currentList] = object->findhigh[object->currentList]->userb; - break; - - case MM_Down: - if (!object->findhigh[object->currentList]) - break; - if (object->findhigh[object->currentList]->next) - { - object->findhigh[object->currentList] = object->findhigh[object->currentList]->next; - break; - } - fallthrough__; - case MM_Home: - object->findhigh[object->currentList] = object->findhigh[object->currentList]->usera; - break; - - case MM_Swap: - object->currentList = !object->currentList; - break; - - default: - break; - } - - Menu_RunInput_FileSelect_MovementVerify(object); -#endif -} - -static void Menu_RunInput_FileSelect_Select(MenuFileSelect_t *object) -{ -#if 0 - if (!object->findhigh[object->currentList]) - return; - - Bstrcat(object->destination, object->findhigh[object->currentList]->name); - - if (object->currentList == 0) - { - Bstrcat(object->destination, "/"); - Bcorrectfilename(object->destination, 1); - - Menu_FileSelectInit(object); - } - else - { - Menu_FileSelect(1); - } -#endif -} - -static void Menu_RunInput(Menu_t *cm) -{ - switch (cm->type) - { - case Panel: - { - auto *panel = (MenuPanel_t*)cm->object; - - if (I_ReturnTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - } - else if (I_PanelUp()) - { - I_PanelUpClear(); - - S_PlaySound(RR ? 335 : KICK_HIT); - Menu_AnimateChange(panel->previousID, panel->previousAnimation); - } - else if (I_PanelDown() || Menu_RunInput_MouseAdvance()) - { - I_PanelDownClear(); - m_mousecaught = 1; - - S_PlaySound(RR ? 335 : KICK_HIT); - Menu_AnimateChange(panel->nextID, panel->nextAnimation); - } - break; - } - - case TextForm: - { - auto *object = (MenuTextForm_t*)cm->object; - int32_t hitstate = I_EnterText(object->input, object->bufsize-1, 0); - - if (hitstate == -1 || Menu_RunInput_MouseReturn()) - { - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - object->input = NULL; - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - Menu_StopTextInput(); - } - else if (hitstate == 1 || Menu_RunInput_MouseAdvance()) - { - m_mousecaught = 1; - - Menu_TextFormSubmit(object->input); - - object->input = NULL; - Menu_StopTextInput(); - } - break; - } - - case FileSelect: - { -#if 0 - auto *object = (MenuFileSelect_t*)cm->object; - - if (I_ReturnTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - object->destination[0] = 0; - - Menu_FileSelect(0); - - Menu_AnimateChange(cm->parentID, MA_Return); - } - else if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_FileSelect_Select(object); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - else if (inputState.GetKeyStatus(sc_Home)) - { - inputState.ClearKeyStatus(sc_Home); - - Menu_RunInput_FileSelect_Movement(object, MM_Home); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - else if (inputState.GetKeyStatus(sc_End)) - { - inputState.ClearKeyStatus(sc_End); - - Menu_RunInput_FileSelect_Movement(object, MM_End); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - else if (inputState.GetKeyStatus(sc_PgUp)) - { - int32_t i; - - CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList]; - - inputState.ClearKeyStatus(sc_PgUp); - - for (i = 0; i < 6; ++i) - { - if (seeker && seeker->prev) - seeker = seeker->prev; - } - - if (seeker) - { - object->findhigh[object->currentList] = seeker; - - Menu_RunInput_FileSelect_MovementVerify(object); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - } - else if (inputState.GetKeyStatus(sc_PgDn)) - { - int32_t i; - - CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList]; - - inputState.ClearKeyStatus(sc_PgDn); - - for (i = 0; i < 6; ++i) - { - if (seeker && seeker->next) - seeker = seeker->next; - } - - if (seeker) - { - object->findhigh[object->currentList] = seeker; - - Menu_RunInput_FileSelect_MovementVerify(object); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - } - else if (I_MenuLeft() || I_MenuRight()) - { - I_MenuLeftClear(); - I_MenuRightClear(); - - if ((object->currentList ? object->fnlist.numdirs : object->fnlist.numfiles) > 0) - { - Menu_RunInput_FileSelect_Movement(object, MM_Swap); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - } - else if (I_MenuUp()) - { - I_MenuUpClear(); - - Menu_RunInput_FileSelect_Movement(object, MM_Up); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - - Menu_RunInput_FileSelect_Movement(object, MM_Down); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - else - { - // JBF 20040208: seek to first name matching pressed character - char ch2, ch; - ch = inputState.keyGetChar(); - if (ch > 0 && ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))) - { - CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList]->usera; - if (ch >= 'a') - ch -= ('a'-'A'); - while (seeker) - { - ch2 = seeker->name[0]; - if (ch2 >= 'a' && ch2 <= 'z') - ch2 -= ('a'-'A'); - if (ch2 == ch) - break; - seeker = seeker->next; - } - if (seeker) - { - object->findhigh[object->currentList] = seeker; - - Menu_RunInput_FileSelect_MovementVerify(object); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - } - } -#endif - Menu_PreInput(NULL); - break; - } - - case Message: - if (I_ReturnTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - } - - if (I_CheckAllInput()) - { - auto *message = (MenuMessage_t*)cm->object; - - I_ClearAllInput(); - - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(message->linkID, message->animation); - } - - Menu_PreInput(NULL); - break; - - case Verify: - if (I_ReturnTrigger() || inputState.GetKeyStatus(sc_N) || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - inputState.ClearKeyStatus(sc_N); - m_mousecaught = 1; - - Menu_Verify(0); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - - S_PlaySound(EXITMENUSOUND); - } - - if (I_AdvanceTrigger() || inputState.GetKeyStatus(sc_Y) || Menu_RunInput_MouseAdvance()) - { - auto *verify = (MenuVerify_t*)cm->object; - - I_AdvanceTriggerClear(); - inputState.ClearKeyStatus(sc_Y); - m_mousecaught = 1; - - Menu_Verify(1); - - Menu_AnimateChange(verify->linkID, verify->animation); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - - Menu_PreInput(NULL); - break; - - case CdPlayer: - { - auto *menu = (MenuMenu_t*)cm->object; - MenuEntry_t *currentry = menu->entrylist[menu->currentEntry]; - - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - mus_enabled = !mus_enabled; - - if (mus_enabled == 0) - S_PauseMusic(true); - else - { - S_PlayRRMusic(2+menu->currentEntry); - S_PauseMusic(false); - } - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - - if (I_ReturnTrigger() || I_EscapeTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - I_EscapeTriggerClear(); - m_mousecaught = 1; - - if (cm->parentID != MENU_CLOSE || (g_player[myconnectindex].ps->gm & MODE_GAME)) - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - } - else if (I_MenuUp() || I_MenuLeft()) - { - I_MenuUpClear(); - I_MenuLeftClear(); - - S_PlaySound(RR ? 335 : KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_Up); - - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (I_MenuDown() || I_MenuRight()) - { - I_MenuDownClear(); - I_MenuRightClear(); - - S_PlaySound(RR ? 335 : KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_Down); - - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (inputState.GetKeyStatus(sc_1)) - { - inputState.ClearKeyStatus(sc_1); - menu->currentEntry = 0; - - S_PlaySound(RR ? 335 : KICK_HIT); - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (inputState.GetKeyStatus(sc_2)) - { - inputState.ClearKeyStatus(sc_2); - menu->currentEntry = 1; - - S_PlaySound(RR ? 335 : KICK_HIT); - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (inputState.GetKeyStatus(sc_3)) - { - inputState.ClearKeyStatus(sc_3); - menu->currentEntry = 2; - - S_PlaySound(RR ? 335 : KICK_HIT); - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (inputState.GetKeyStatus(sc_4)) - { - inputState.ClearKeyStatus(sc_4); - menu->currentEntry = 3; - - S_PlaySound(RR ? 335 : KICK_HIT); - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (inputState.GetKeyStatus(sc_5)) - { - inputState.ClearKeyStatus(sc_5); - menu->currentEntry = 4; - - S_PlaySound(RR ? 335 : KICK_HIT); - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (inputState.GetKeyStatus(sc_6)) - { - inputState.ClearKeyStatus(sc_6); - menu->currentEntry = 5; - - S_PlaySound(RR ? 335 : KICK_HIT); - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (inputState.GetKeyStatus(sc_7)) - { - inputState.ClearKeyStatus(sc_7); - menu->currentEntry = 6; - - S_PlaySound(RR ? 335 : KICK_HIT); - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - else if (inputState.GetKeyStatus(sc_8)) - { - inputState.ClearKeyStatus(sc_8); - menu->currentEntry = 7; - - S_PlaySound(RR ? 335 : KICK_HIT); - if (MusicEnabled()) - { - S_StopMusic(); - S_PlayRRMusic(2+menu->currentEntry); - } - } - - if (currentry != NULL) - Menu_PreInput(currentry); - - break; - } - - case Menu: - { - int32_t state; - - auto *menu = (MenuMenu_t*)cm->object; - MenuEntry_t *currentry = menu->entrylist[menu->currentEntry]; - - state = Menu_DetermineSpecialState(currentry); - - if (state == 0) - { - if (currentry != NULL) - switch (currentry->type) - { - case Dummy: - case Spacer: - break; - case Link: - if (currentry->flags & MEF_Disabled) - break; - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_EntryLink_Activate(currentry); - - if (g_player[myconnectindex].ps->gm&MODE_MENU) // for skill selection - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - break; - case Option: - { - auto *object = (MenuOption_t*)currentry->entry; - - if (currentry->flags & MEF_Disabled) - break; - - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_EntryOption_Activate(currentry, object); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - else if (I_MenuRight()) - { - I_MenuRightClear(); - - Menu_RunInput_EntryOption_Movement(currentry, object, MM_Right); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - else if (I_MenuLeft()) - { - I_MenuLeftClear(); - - Menu_RunInput_EntryOption_Movement(currentry, object, MM_Left); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - } - break; - case Custom2Col: - if (I_MenuLeft() || I_MenuRight()) - { - I_MenuLeftClear(); - I_MenuRightClear(); - - Menu_RunInput_Menu_Movement(menu, MM_Swap); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - - if (currentry->flags & MEF_Disabled) - break; - - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_EntryCustom2Col_Activate(currentry); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - break; - case RangeInt32: - { - auto *object = (MenuRangeInt32_t*)currentry->entry; - - if (currentry->flags & MEF_Disabled) - break; - - if (I_SliderLeft()) - { - I_SliderLeftClear(); - - Menu_RunInput_EntryRangeInt32_Movement(currentry, object, MM_Left); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - else if (I_SliderRight()) - { - I_SliderRightClear(); - - Menu_RunInput_EntryRangeInt32_Movement(currentry, object, MM_Right); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - break; - } - case RangeFloat: - { - auto *object = (MenuRangeFloat_t*)currentry->entry; - - if (currentry->flags & MEF_Disabled) - break; - - if (I_SliderLeft()) - { - I_SliderLeftClear(); - - Menu_RunInput_EntryRangeFloat_Movement(currentry, object, MM_Left); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - else if (I_SliderRight()) - { - I_SliderRightClear(); - - Menu_RunInput_EntryRangeFloat_Movement(currentry, object, MM_Right); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - break; - } -#ifdef MENU_ENABLE_RANGEDOUBLE - case RangeDouble: - { - MenuRangeDouble_t *object = (MenuRangeDouble_t*)currentry->entry; - - if (currentry->flags & MEF_Disabled) - break; - - if (I_SliderLeft()) - { - I_SliderLeftClear(); - - Menu_RunInput_EntryRangeDouble_Movement(/*currentry, */object, MM_Left); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - else if (I_SliderRight()) - { - I_SliderRightClear(); - - Menu_RunInput_EntryRangeDouble_Movement(/*currentry, */object, MM_Right); - - S_PlaySound(RR ? 335 : KICK_HIT); - } - break; - } -#endif - - case String: - { - if (currentry->flags & MEF_Disabled) - break; - - if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - Menu_RunInput_EntryString_Activate(currentry); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - - break; - } - } - - if (I_ReturnTrigger() || I_EscapeTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - I_EscapeTriggerClear(); - m_mousecaught = 1; - - if (cm->parentID != MENU_CLOSE || (g_player[myconnectindex].ps->gm & MODE_GAME)) - S_PlaySound(EXITMENUSOUND); - - Menu_AnimateChange(cm->parentID, cm->parentAnimation); - } - else if (inputState.GetKeyStatus(sc_Home)) - { - inputState.ClearKeyStatus(sc_Home); - - S_PlaySound(RR ? 335 : KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_Home); - } - else if (inputState.GetKeyStatus(sc_End)) - { - inputState.ClearKeyStatus(sc_End); - - S_PlaySound(RR ? 335 : KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_End); - } - else if (I_MenuUp()) - { - I_MenuUpClear(); - - S_PlaySound(RR ? 335 : KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_Up); - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - - S_PlaySound(RR ? 335 : KICK_HIT); - - currentry = Menu_RunInput_Menu_Movement(menu, MM_Down); - } - - if (currentry != NULL) - Menu_PreInput(currentry); - } - else if (state == 1) - { - if (currentry->type == String) - { - auto *object = (MenuString_t*)currentry->entry; - - int32_t hitstate = I_EnterText(object->editfield, object->bufsize-1, object->flags); - - if (hitstate == -1 || Menu_RunInput_MouseReturn()) - { - m_mousecaught = 1; - - Menu_RunInput_EntryString_Cancel(/*currentry, */object); - - S_PlaySound(EXITMENUSOUND); - } - else if (hitstate == 1) - { - Menu_RunInput_EntryString_Submit(/*currentry, */object); - - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - } - } - else if (state == 2) - { - if (currentry->type == Option) - { - auto *object = (MenuOption_t*)currentry->entry; - - if (I_ReturnTrigger() || Menu_RunInput_MouseReturn()) - { - I_ReturnTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - object->options->currentEntry = -1; - } - else if (I_AdvanceTrigger()) - { - I_AdvanceTriggerClear(); - - if (!Menu_RunInput_EntryOptionList_Activate(currentry, object)) - S_PlaySound(RR ? 341 : PISTOL_BODYHIT); - } - else if (inputState.GetKeyStatus(sc_Home)) - { - inputState.ClearKeyStatus(sc_Home); - - S_PlaySound(RR ? 335 : KICK_HIT); - - Menu_RunInput_EntryOptionList_Movement(object, MM_Home); - } - else if (inputState.GetKeyStatus(sc_End)) - { - inputState.ClearKeyStatus(sc_End); - - S_PlaySound(RR ? 335 : KICK_HIT); - - Menu_RunInput_EntryOptionList_Movement(object, MM_End); - } - else if (I_MenuUp()) - { - I_MenuUpClear(); - - S_PlaySound(RR ? 335 : KICK_HIT); - - Menu_RunInput_EntryOptionList_Movement(object, MM_Up); - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - - S_PlaySound(RR ? 335 : KICK_HIT); - - Menu_RunInput_EntryOptionList_Movement(object, MM_Down); - } - } - else if (currentry->type == Custom2Col) - { - if (I_EscapeTrigger() || Menu_RunInput_MouseReturn()) - { - I_EscapeTriggerClear(); - m_mousecaught = 1; - - S_PlaySound(EXITMENUSOUND); - - ((MenuCustom2Col_t*)currentry->entry)->screenOpen = 0; - } - else if (Menu_PreCustom2ColScreen(currentry)) - ((MenuCustom2Col_t*)currentry->entry)->screenOpen = 0; - } - } - - break; - } - } -} - -// This function MUST NOT RECURSE. That is why Menu_Run is separate. -void M_DisplayMenus(void) -{ - vec2_t origin = { 0, 0 }, previousOrigin = { 0, 0 }; - - Net_GetPackets(); - - if ((g_player[myconnectindex].ps->gm&MODE_MENU) == 0) - { - return; - } - - if (!Menu_IsTextInput(m_currentMenu) && inputState.GetKeyStatus(sc_Q)) - Menu_AnimateChange(MENU_QUIT, MA_Advance); - - int32_t mousestatus = inputState.mouseReadAbs(&m_mousepos); - if (mousestatus && inputState.mouseClickState() == MOUSE_PRESSED) - m_mousedownpos = m_mousepos; - - Menu_RunInput(m_currentMenu); - - g_player[myconnectindex].ps->gm &= (0xff-MODE_TYPE); - // g_player[myconnectindex].ps->fta = 0; - - int32_t const backgroundOK = ud.menubackground && Menu_BlackTranslucentBackgroundOK(g_currentMenu); - - // need EVENT_DISPLAYMENUBACKGROUND here - - if (((g_player[myconnectindex].ps->gm&MODE_GAME) || ud.recstat==2) && backgroundOK) - videoFadeToBlack(1); - - if (Menu_UpdateScreenOK(g_currentMenu)) - G_UpdateScreenArea(); - -#if !defined EDUKE32_TOUCH_DEVICES - if (m_menuchange_watchpoint > 0) - m_menuchange_watchpoint++; -#endif - - if (totalclock < m_animation.start) - { - m_animation.start = 0; - m_animation.length = 0; - } - - // Determine animation values. - if (totalclock < m_animation.start + m_animation.length) - { - const int32_t screenwidth = scale(240<<16, xdim, ydim); - - origin.x = mulscale15(screenwidth, m_animation.in(&m_animation)); - previousOrigin.x = mulscale15(screenwidth, m_animation.out(&m_animation)); - } - - if (m_parentMenu && backgroundOK) - { - Menu_Run(m_parentMenu, origin); - } - - // Display the menu, with a transition animation if applicable. - if (totalclock < m_animation.start + m_animation.length) - { - Menu_Run(m_animation.previous, previousOrigin); - Menu_Run(m_animation.current, origin); - } - else - Menu_Run(m_currentMenu, origin); - -#if !defined EDUKE32_TOUCH_DEVICES - if (m_menuchange_watchpoint >= 3) - m_menuchange_watchpoint = 0; -#endif - -#if !defined EDUKE32_TOUCH_DEVICES - if (tilesiz[CROSSHAIR].x > 0 && mousestatus) -#else - if (mousestatus) -#endif - { -#if !defined EDUKE32_TOUCH_DEVICES - if (!MOUSEACTIVECONDITION) - m_mousewake_watchpoint = 1; -#endif - - if (MOUSEACTIVECONDITIONAL(inputState.mouseAdvanceClickState()) || m_mousepos.x != m_prevmousepos.x || m_mousepos.y != m_prevmousepos.y) - { - m_prevmousepos = m_mousepos; - m_mouselastactivity = (int32_t) totalclock; - } -#if !defined EDUKE32_TOUCH_DEVICES - else - m_mousewake_watchpoint = 0; -#endif - - m_mousecaught = 0; - } - else - { - m_mouselastactivity = -M_MOUSETIMEOUT; - -#if !defined EDUKE32_TOUCH_DEVICES - m_mousewake_watchpoint = 0; -#endif - } - -#ifndef EDUKE32_TOUCH_DEVICES - // Display the mouse cursor, except on touch devices. - if (MOUSEACTIVECONDITION) - { - int32_t a = CROSSHAIR; - - if ((unsigned) a < MAXTILES) - { - vec2_t cursorpos = m_mousepos; - int32_t z = RR ? 32768 : 65536; - uint8_t p = CROSSHAIR_PAL; - uint32_t o = 2; - - int32_t alpha = CURSORALPHA; - - rotatesprite_fs_alpha(cursorpos.x, cursorpos.y, z, 0, a, 0, p, o, alpha); - } - } - else - inputState.clearMouseClickState(); - -#endif - - if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU) - { - G_UpdateScreenArea(); - CAMERACLOCK = (int32_t) totalclock; - CAMERADIST = 65536; - } -} - -bool GameInterface::mouseInactiveConditional(bool condition) -{ - return MOUSEINACTIVECONDITIONAL(condition); -} END_RR_NS diff --git a/source/rr/src/menus.h b/source/rr/src/menus.h index 7bdf57a7a..dc2023d67 100644 --- a/source/rr/src/menus.h +++ b/source/rr/src/menus.h @@ -27,6 +27,38 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_RR_NS +// a subset of screentext parameters, restricted because menus require accessibility +typedef struct MenuFont_t +{ + // int32_t xspace, yline; + vec2_t emptychar, between; + int32_t zoom; + int32_t cursorLeftPosition, cursorCenterPosition, cursorScale, cursorScale2, cursorScale3; + int32_t textflags; + int16_t tilenum; + // selected shade glows, deselected shade is used by Blood, disabled shade is used by SW + int8_t shade_deselected, shade_disabled; + uint8_t pal; + uint8_t pal_selected, pal_deselected, pal_disabled; + uint8_t pal_selected_right, pal_deselected_right, pal_disabled_right; + + int32_t get_yline() const { return mulscale16(emptychar.y, zoom); } +} MenuFont_t; + +extern MenuFont_t MF_Redfont, MF_Bluefont, MF_Minifont; + +void Menu_Init(void); +inline int G_CheckPlayerColor(int color) +{ + static int32_t player_pals[] = { 0, 9, 10, 11, 12, 13, 14, 15, 16, 21, 23, }; + if (color >= 0 && color < 10) return player_pals[color]; + return 0; +} + + +#if 0 + + enum MenuIndex_t { MENU_NULL = INT32_MIN, // sentinel for "do nothing" MENU_CLOSE = -2, // sentinel for "close the menu"/"no menu" @@ -141,25 +173,6 @@ typedef enum MenuAnimationType_t MA_Advance, } MenuAnimationType_t; -// a subset of screentext parameters, restricted because menus require accessibility -typedef struct MenuFont_t -{ -// int32_t xspace, yline; - vec2_t emptychar, between; - int32_t zoom; - int32_t cursorLeftPosition, cursorCenterPosition, cursorScale, cursorScale2, cursorScale3; - int32_t textflags; - int16_t tilenum; - // selected shade glows, deselected shade is used by Blood, disabled shade is used by SW - int8_t shade_deselected, shade_disabled; - uint8_t pal; - uint8_t pal_selected, pal_deselected, pal_disabled; - uint8_t pal_selected_right, pal_deselected_right, pal_disabled_right; - - int32_t get_yline() const { return mulscale16(emptychar.y, zoom); } -} MenuFont_t; - - typedef enum MenuEntryType_t { @@ -483,7 +496,6 @@ extern int32_t voting; int Menu_Change(MenuID_t cm); void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype); int32_t Menu_IsTextInput(Menu_t *cm); -int G_CheckPlayerColor(int color); void Menu_Init(void); void Menu_Open(uint8_t playerID); void Menu_Close(uint8_t playerID); @@ -505,6 +517,8 @@ extern int32_t m_mousewake_watchpoint, m_menuchange_watchpoint; # define MOUSEINACTIVECONDITIONAL(condition) (!MOUSEACTIVECONDITION && (condition)) # define MOUSEWATCHPOINTCONDITIONAL(condition) ((condition) || m_mousewake_watchpoint || m_menuchange_watchpoint == 3) +#endif + END_RR_NS #endif diff --git a/source/rr/src/namesdyn.cpp b/source/rr/src/namesdyn.cpp index 4a3ee6a87..99bea9a07 100644 --- a/source/rr/src/namesdyn.cpp +++ b/source/rr/src/namesdyn.cpp @@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "namesdyn.h" #include "global.h" +#include "gamecontrol.h" BEGIN_RR_NS @@ -2965,6 +2966,7 @@ void G_InitDynamicTiles(void) *(g_dynTileList[i].dynvalptr) = -g_dynTileList[i].staticval_rr; if (RRRA && *(g_dynTileList[i].dynvalptr) == -UFO1__STATICRR) *(g_dynTileList[i].dynvalptr) = -UFO1__STATICRRRA; DynamicTileMap[*(g_dynTileList[i].dynvalptr)] = g_dynTileList[i].staticval_rr; + NameToTileIndex.Insert(g_dynTileList[i].str, *(g_dynTileList[i].dynvalptr)); } for (i = 0; g_dynWeaponList[i].staticval >= 0; i++) *(g_dynWeaponList[i].dynvalptr) = g_dynWeaponList[i].staticval_rr; @@ -2974,7 +2976,10 @@ void G_InitDynamicTiles(void) for (i=0; g_dynTileList[i].staticval >= 0; i++) if (g_dynTileList[i].staticval > 0) + { DynamicTileMap[*(g_dynTileList[i].dynvalptr)] = g_dynTileList[i].staticval; + NameToTileIndex.Insert(g_dynTileList[i].str, *(g_dynTileList[i].dynvalptr)); + } for (i=0; g_dynWeaponList[i].staticval >= 0; i++) DynamicWeaponMap[*(g_dynWeaponList[i].dynvalptr)] = g_dynWeaponList[i].staticval; diff --git a/source/rr/src/net.cpp b/source/rr/src/net.cpp index 7506641c5..993283e75 100644 --- a/source/rr/src/net.cpp +++ b/source/rr/src/net.cpp @@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "savegame.h" #include "input.h" #include "m_crc32.h" +#include "mapinfo.h" #include "enet.h" @@ -1801,7 +1802,7 @@ void Net_GetInput(void) if (g_player[myconnectindex].movefifoend&(g_movesPerPacket-1)) { - copybufbyte(&inputfifo[(g_player[myconnectindex].movefifoend-1)&(MOVEFIFOSIZ-1)][myconnectindex], + memcpy(&inputfifo[(g_player[myconnectindex].movefifoend-1)&(MOVEFIFOSIZ-1)][myconnectindex], &inputfifo[g_player[myconnectindex].movefifoend&(MOVEFIFOSIZ-1)][myconnectindex],sizeof(input_t)); g_player[myconnectindex].movefifoend++; return; @@ -2179,7 +2180,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) continue; } - copybufbyte(&osyn[i],&nsyn[i],sizeof(input_t)); + memcpy(&osyn[i],&nsyn[i],sizeof(input_t)); if (l&1) nsyn[i].fvel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2; if (l&2) nsyn[i].svel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2; if (l&4) @@ -2218,7 +2219,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) if (i != myconnectindex) for (j=g_movesPerPacket-1;j>=1;j--) { - copybufbyte(&nsyn[i],&inputfifo[g_player[i].movefifoend&(MOVEFIFOSIZ-1)][i],sizeof(input_t)); + memcpy(&nsyn[i],&inputfifo[g_player[i].movefifoend&(MOVEFIFOSIZ-1)][i],sizeof(input_t)); g_player[i].movefifoend++; } @@ -2232,7 +2233,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) osyn = (input_t *)&inputfifo[(g_player[other].movefifoend-1)&(MOVEFIFOSIZ-1)][0]; nsyn = (input_t *)&inputfifo[(g_player[other].movefifoend)&(MOVEFIFOSIZ-1)][0]; - copybufbyte(&osyn[other],&nsyn[other],sizeof(input_t)); + memcpy(&osyn[other],&nsyn[other],sizeof(input_t)); if (k&1) nsyn[other].fvel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2; if (k&2) nsyn[other].svel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2; if (k&4) @@ -2271,7 +2272,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) for (i=g_movesPerPacket-1;i>=1;i--) { - copybufbyte(&nsyn[other],&inputfifo[g_player[other].movefifoend&(MOVEFIFOSIZ-1)][other],sizeof(input_t)); + memcpy(&nsyn[other],&inputfifo[g_player[other].movefifoend&(MOVEFIFOSIZ-1)][other],sizeof(input_t)); g_player[other].movefifoend++; } @@ -2295,7 +2296,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) osyn = (input_t *)&inputfifo[(g_player[other].movefifoend-1)&(MOVEFIFOSIZ-1)][0]; nsyn = (input_t *)&inputfifo[(g_player[other].movefifoend)&(MOVEFIFOSIZ-1)][0]; - copybufbyte(&osyn[other],&nsyn[other],sizeof(input_t)); + memcpy(&osyn[other],&nsyn[other],sizeof(input_t)); k = packbuf[j] + (int)(packbuf[j+1]<<8); j += 2; @@ -2331,7 +2332,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) for (i=g_movesPerPacket-1;i>=1;i--) { - copybufbyte(&nsyn[other],&inputfifo[g_player[other].movefifoend&(MOVEFIFOSIZ-1)][other],sizeof(input_t)); + memcpy(&nsyn[other],&inputfifo[g_player[other].movefifoend&(MOVEFIFOSIZ-1)][other],sizeof(input_t)); g_player[other].movefifoend++; } @@ -2359,340 +2360,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) //case PACKET_TYPE_QUIT: // G_GameExit(" "); // break; -#if 0 - default: - switch (packbuf[0]) - { - case PACKET_TYPE_MESSAGE: - //slaves in M/S mode only send to master - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - { - if (packbuf[1] == 255) - { - //Master re-transmits message to all others - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) - Net_SendPacket(i,packbuf,packbufleng); - } - else if (((int)packbuf[1]) != myconnectindex) - { - //Master re-transmits message not intended for master - Net_SendPacket((int)packbuf[1],packbuf,packbufleng); - break; - } - } - Bstrcpy(recbuf,(char*)packbuf+2); - recbuf[packbufleng-2] = 0; - - G_AddUserQuote(recbuf); - S_PlaySound(EXITMENUSOUND); - - pus = NUMPAGES; - pub = NUMPAGES; - - break; - - case PACKET_TYPE_NEW_GAME: - //Slaves in M/S mode only send to master - //Master re-transmits message to all others - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) Net_SendPacket(i,packbuf,packbufleng); - - if (vote_map != -1 || vote_episode != -1 || voting != -1) - G_AddUserQuote("VOTE SUCCEEDED"); - - m_level_number = ud.level_number = packbuf[1]; - ud.m_volume_number = ud.volume_number = packbuf[2]; - ud.m_player_skill = ud.player_skill = packbuf[3]; - - // Non-menu variables handled by G_EnterLevel - ud.m_monsters_off = packbuf[4]; - ud.m_respawn_monsters = packbuf[5]; - ud.m_respawn_items = packbuf[6]; - ud.m_respawn_inventory = packbuf[7]; - m_coop = packbuf[8]; - m_marker = packbuf[9]; - m_ffire = packbuf[10]; - m_noexits = packbuf[11]; - //ud.m_weaponstay = packbuf[12]; - - for (int TRAVERSE_CONNECT(i)) - { - P_ResetWeapons(i); - P_ResetInventory(i); - } - - G_NewGame(ud.volume_number,ud.level_number,ud.player_skill); - - if (G_EnterLevel(MODE_GAME)) G_BackToMenu(); - - break; - - case PACKET_TYPE_INIT_SETTINGS: - //Slaves in M/S mode only send to master - //Master re-transmits message to all others - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i]) - if (i != other) Net_SendPacket(i, packbuf, packbufleng); - - m_level_number = ud.level_number = packbuf[1]; - ud.m_volume_number = ud.volume_number = packbuf[2]; - ud.m_player_skill = ud.player_skill = packbuf[3]; - - // Non-menu variables handled by G_EnterLevel - ud.m_monsters_off = packbuf[4]; - ud.m_respawn_monsters = packbuf[5]; - ud.m_respawn_items = packbuf[6]; - ud.m_respawn_inventory = packbuf[7]; - m_coop = packbuf[8]; - m_marker = packbuf[9]; - m_ffire = packbuf[10]; - m_noexits = packbuf[11]; - //ud.m_weaponstay = packbuf[12]; - break; - - case PACKET_TYPE_VERSION: - //slaves in M/S mode only send to master - //Master re-transmits message to all others - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) Net_SendPacket(i,packbuf,packbufleng); - - if (packbuf[2] != (char)atoi(s_buildDate)) - { - initprintf("Player has version %d, expecting %d\n",packbuf[2],(char)atoi(s_buildDate)); - G_GameExit("You cannot play with different versions of EDuke32!"); - } - if (packbuf[3] != (char)BYTEVERSION) - { - initprintf("Player has version %d, expecting %d (%d, %d, %d)\n",packbuf[3],BYTEVERSION, NETVERSION, PLUTOPAK, VOLUMEONE); - G_GameExit("You cannot play Duke with different versions!"); - } - if (packbuf[4] > g_numSyncBytes) - { - initprintf("Sync debugging enabled\n"); - g_numSyncBytes = packbuf[4]; - } - - break; - - case PACKET_TYPE_PLAYER_OPTIONS: - //slaves in M/S mode only send to master - //Master re-transmits message to all others - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) Net_SendPacket(i,packbuf,packbufleng); - - other = packbuf[1]; - i = 2; - - g_player[other].ps->aim_mode = packbuf[i++]; - g_player[other].ps->auto_aim = packbuf[i++]; - g_player[other].ps->weaponswitch = packbuf[i++]; - g_player[other].ps->palookup = g_player[other].pcolor = packbuf[i++]; - g_player[other].pteam = packbuf[i++]; - - break; - - //case PACKET_TYPE_FRAGLIMIT_CHANGED: - // //slaves in M/S mode only send to master - // //Master re-transmits message to all others - // if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - // for (i = connectpoint2[connecthead];i >= 0;i = connectpoint2[i]) - // if (i != other) Net_SendPacket(i, packbuf, packbufleng); - // - // ud.fraglimit = packbuf[2]; - // - // Bsprintf(tempbuf, "FRAGLIMIT CHANGED TO %d", ud.fraglimit); - // G_AddUserQuote(tempbuf); - // break; - - case PACKET_TYPE_EOL: - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) Net_SendPacket(i,packbuf,packbufleng); - - for (TRAVERSE_CONNECT(i)) - g_player[i].ps->gm = MODE_EOL; - - ud.level_number = packbuf[1]; - m_level_number = ud.level_number; - ud.from_bonus = packbuf[2]; - break; - - case PACKET_TYPE_PLAYER_NAME: - //slaves in M/S mode only send to master - //Master re-transmits message to all others - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) Net_SendPacket(i,packbuf,packbufleng); - - other = packbuf[1]; - - for (i=2;packbuf[i];i++) - g_player[other].user_name[i-2] = packbuf[i]; - g_player[other].user_name[i-2] = 0; - i++; - - initprintf("Player %d's name is now %s\n", other, g_player[other].user_name); - - break; - - case PACKET_TYPE_WEAPON_CHOICE: - //slaves in M/S mode only send to master - //Master re-transmits message to all others - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) Net_SendPacket(i,packbuf,packbufleng); - - other = packbuf[1]; - - i = 2; - - j = i; //This used to be Duke packet #9... now concatenated with Duke packet #6 - for (;i-j<10;i++) g_player[other].wchoice[i-j] = packbuf[i]; - - break; - case PACKET_TYPE_RTS: - //slaves in M/S mode only send to master - //Master re-transmits message to all others - if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) Net_SendPacket(i,packbuf,packbufleng); - - G_StartRTS(packbuf[1], other); - break; - - case PACKET_TYPE_MENU_LEVEL_QUIT: - //slaves in M/S mode only send to master - if (myconnectindex == connecthead) - { - //Master re-transmits message to all others - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) - Net_SendPacket(i,packbuf,packbufleng); - } - - G_GameExit("Game aborted from menu; disconnected."); - - break; - - case PACKET_TYPE_USER_MAP: - //slaves in M/S mode only send to master - if (myconnectindex == connecthead) - { - //Master re-transmits message to all others - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) - Net_SendPacket(i,packbuf,packbufleng); - } - - Bstrcpy(boardfilename,(char*)packbuf+1); - boardfilename[packbufleng-1] = 0; - Bcorrectfilename(boardfilename,0); - if (boardfilename[0] != 0) - { - if (testkopen(boardfilename,0)) - { - Bmemset(boardfilename,0,sizeof(boardfilename)); - Net_SendUserMapName(); - } - } - - if (m_level_number == 7 && ud.m_volume_number == 0 && boardfilename[0] == 0) - m_level_number = 0; - - break; - - case PACKET_TYPE_MAP_VOTE: - case PACKET_TYPE_MAP_VOTE_INITIATE: - case PACKET_TYPE_MAP_VOTE_CANCEL: - - if (myconnectindex == connecthead) - { - //Master re-transmits message to all others - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - if (i != other) - Net_SendPacket(i,packbuf,packbufleng); - } - - switch (packbuf[0]) - { - case PACKET_TYPE_MAP_VOTE: - if (voting == myconnectindex && g_player[packbuf[1]].gotvote == 0) - { - g_player[packbuf[1]].gotvote = 1; - g_player[packbuf[1]].vote = packbuf[2]; - Bsprintf(tempbuf,"Confirmed vote from %s",g_player[packbuf[1]].user_name); - G_AddUserQuote(tempbuf); - } - break; - - case PACKET_TYPE_MAP_VOTE_INITIATE: // call map vote - /* if (g_networkBroadcastMode == 0 && packbuf[1] == connecthead) - break; // ignore this from master */ - voting = packbuf[1]; - vote_episode = packbuf[2]; - vote_map = packbuf[3]; - - Bsprintf(tempbuf,"%s^00 HAS CALLED A VOTE TO CHANGE MAP TO %s (E%dL%d)", - g_player[packbuf[1]].user_name, - g_mapInfo[(unsigned char)(packbuf[2]*MAXLEVELS + packbuf[3])].name, - packbuf[2]+1,packbuf[3]+1); - G_AddUserQuote(tempbuf); - - Bsprintf(tempbuf,"Press F1 to Accept, F2 to Decline"); - G_AddUserQuote(tempbuf); - - for (i=MAXPLAYERS-1;i>=0;i--) - { - g_player[i].vote = 0; - g_player[i].gotvote = 0; - } - g_player[voting].gotvote = g_player[voting].vote = 1; - break; - - case PACKET_TYPE_MAP_VOTE_CANCEL: // cancel map vote - if (voting == packbuf[1]) - { - voting = -1; - i = 0; - for (j=MAXPLAYERS-1;j>=0;j--) - i += g_player[j].gotvote; - - if (i != numplayers) - Bsprintf(tempbuf,"%s^00 has canceled the vote",g_player[(unsigned char)packbuf[1]].user_name); - else Bsprintf(tempbuf,"Vote failed"); - for (i=MAXPLAYERS-1;i>=0;i--) - { - g_player[i].vote = 0; - g_player[i].gotvote = 0; - } - G_AddUserQuote(tempbuf); - } - break; - } - break; - - //case PACKET_TYPE_LOAD_GAME: - // //Slaves in M/S mode only send to master - // //Master re-transmits message to all others - // if ((!g_networkBroadcastMode) && (myconnectindex == connecthead)) - // for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - // if (i != other) Net_SendPacket(i,packbuf,packbufleng); - // - // multiflag = 2; - // multiwhat = 0; - // multiwho = packbuf[2]; //other: need to send in m/s mode because of possible re-transmit - // multipos = packbuf[1]; - // G_LoadPlayer(multipos); - // multiflag = 0; - // break; - } - break; -#endif } } @@ -2863,7 +2531,6 @@ void Net_ReceiveDisconnect(ENetEvent *event) void Net_GetPackets(void) { - timerUpdate(); MUSIC_Update(); G_HandleSpecialKeys(); @@ -3427,10 +3094,10 @@ void Net_SendClientInfo(void) l += 32; tempbuf[l++] = 0; - tempbuf[l++] = g_player[myconnectindex].ps->aim_mode = in_aimmode; + tempbuf[l++] = g_player[myconnectindex].ps->aim_mode = in_mousemode; tempbuf[l++] = g_player[myconnectindex].ps->auto_aim = cl_autoaim; tempbuf[l++] = g_player[myconnectindex].ps->weaponswitch = cl_weaponswitch; - tempbuf[l++] = g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = playercolor; + tempbuf[l++] = g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = G_CheckPlayerColor(playercolor); tempbuf[l++] = g_player[myconnectindex].pteam = playerteam; @@ -3520,7 +3187,7 @@ void Net_ReceiveUserMapName(uint8_t *pbuf, int32_t packbufleng) Bcorrectfilename(boardfilename,0); if (boardfilename[0] != 0) { - if (testkopen(boardfilename,0)) + if (fileSystem.FileExists(boardfilename)) { Bmemset(boardfilename,0,sizeof(boardfilename)); Net_SendUserMapName(); @@ -3850,7 +3517,7 @@ void Net_ReceiveMapVoteInitiate(uint8_t *pbuf) Bsprintf(tempbuf,"%s^00 has called a vote to change map to %s (E%dL%d)", g_player[voting].user_name, - g_mapInfo[(uint8_t)(vote_episode*MAXLEVELS + vote_map)].name, + mapList[(uint8_t)(vote_episode*MAXLEVELS + vote_map)].DisplayName(), vote_episode+1,vote_map+1); G_AddUserQuote(tempbuf); diff --git a/source/rr/src/osdcmds.cpp b/source/rr/src/osdcmds.cpp index c42665d92..57b59fec9 100644 --- a/source/rr/src/osdcmds.cpp +++ b/source/rr/src/osdcmds.cpp @@ -29,120 +29,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "osdcmds.h" #include "savegame.h" #include "sbar.h" +#include "mapinfo.h" BEGIN_RR_NS struct osdcmd_cheatsinfo osdcmd_cheatsinfo_stat = { -1, 0, 0 }; -static int osdcmd_changelevel(osdcmdptr_t parm) -{ - int32_t volume=0,level; - char *p; - - if (!VOLUMEONE) - { - if (parm->numparms != 2) return OSDCMD_SHOWHELP; - - volume = strtol(parm->parms[0], &p, 10) - 1; - if (p[0]) return OSDCMD_SHOWHELP; - level = strtol(parm->parms[1], &p, 10) - 1; - if (p[0]) return OSDCMD_SHOWHELP; - } - else - { - if (parm->numparms != 1) return OSDCMD_SHOWHELP; - - level = strtol(parm->parms[0], &p, 10) - 1; - if (p[0]) return OSDCMD_SHOWHELP; - } - - if (volume < 0) return OSDCMD_SHOWHELP; - if (level < 0) return OSDCMD_SHOWHELP; - - if (!VOLUMEONE) - { - if (volume > g_volumeCnt) - { - OSD_Printf("changelevel: invalid volume number (range 1-%d)\n",g_volumeCnt); - return OSDCMD_OK; - } - } - - if (level > MAXLEVELS || g_mapInfo[volume *MAXLEVELS+level].filename == NULL) - { - OSD_Printf("changelevel: invalid level number\n"); - return OSDCMD_SHOWHELP; - } - - if (numplayers > 1) - { - /* - if (g_netServer) - Net_NewGame(volume,level); - else if (voting == -1) - { - ud.m_volume_number = volume; - m_level_number = level; - - if (g_player[myconnectindex].ps->i) - { - int32_t i; - - for (i=0; igm & MODE_GAME) - { - // in-game behave like a cheat - osdcmd_cheatsinfo_stat.cheatnum = CHEAT_SCOTTY; - osdcmd_cheatsinfo_stat.volume = volume; - osdcmd_cheatsinfo_stat.level = level; - } - else - { - // out-of-game behave like a menu command - osdcmd_cheatsinfo_stat.cheatnum = -1; - - ud.m_volume_number = volume; - m_level_number = level; - - ud.m_monsters_off = 0; - ud.monsters_off = 0; - - ud.m_respawn_items = 0; - ud.m_respawn_inventory = 0; - - ud.multimode = 1; - - G_NewGame_EnterLevel(); - } - - return OSDCMD_OK; -} - static int osdcmd_map(osdcmdptr_t parm) { char filename[BMAX_PATH]; @@ -157,7 +49,7 @@ static int osdcmd_map(osdcmdptr_t parm) maybe_append_ext(filename, sizeof(filename), parm->parms[0], ".map"); - if (!testkopen(filename,0)) + if (!fileSystem.FileExists(filename)) { OSD_Printf(OSD_ERROR "map: file \"%s\" not found.\n", filename); return OSDCMD_OK; @@ -169,48 +61,6 @@ static int osdcmd_map(osdcmdptr_t parm) if (numplayers > 1) { - /* - if (g_netServer) - { - Net_SendUserMapName(); - ud.m_volume_number = 0; - m_level_number = 7; - Net_NewGame(ud.m_volume_number, m_level_number); - } - else if (voting == -1) - { - Net_SendUserMapName(); - - ud.m_volume_number = 0; - m_level_number = 7; - - if (g_player[myconnectindex].ps->i) - { - int32_t i; - - for (i=0; inumparms == 1) - { - int32_t sel = G_GetMusicIdx(parm->parms[0]); - - if (sel == -1) - return OSDCMD_SHOWHELP; - - if (sel == -2) - { - OSD_Printf("%s is not a valid episode/level number pair\n", parm->parms[0]); - return OSDCMD_OK; - } - - if (!S_TryPlayLevelMusic(sel)) - { - G_PrintCurrentMusic(); - } - else - { - OSD_Printf("No music defined for %s\n", parm->parms[0]); - } - - return OSDCMD_OK; - } - - return OSDCMD_SHOWHELP; -} - int osdcmd_restartmap(osdcmdptr_t UNUSED(parm)) { UNREFERENCED_CONST_PARAMETER(parm); @@ -519,27 +334,6 @@ static int osdcmd_spawn(osdcmdptr_t parm) return OSDCMD_OK; } -static int osdcmd_cmenu(osdcmdptr_t parm) -{ - if (parm->numparms != 1) - return OSDCMD_SHOWHELP; - - if (numplayers > 1) - { - OSD_Printf("Command not allowed in multiplayer\n"); - return OSDCMD_OK; - } - - if ((g_player[myconnectindex].ps->gm & MODE_MENU) != MODE_MENU) - Menu_Open(myconnectindex); - - Menu_Change(Batol(parm->parms[0])); - - return OSDCMD_OK; -} - - - static int osdcmd_crosshaircolor(osdcmdptr_t parm) { @@ -646,63 +440,6 @@ void onvideomodechange(int32_t newmode) } -static int osdcmd_quicksave(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - if (!(g_player[myconnectindex].ps->gm & MODE_GAME)) - OSD_Printf("quicksave: not in a game.\n"); - else g_doQuickSave = 1; - return OSDCMD_OK; -} - -static int osdcmd_quickload(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - if (!(g_player[myconnectindex].ps->gm & MODE_GAME)) - OSD_Printf("quickload: not in a game.\n"); - else g_doQuickSave = 2; - return OSDCMD_OK; -} - -static int osdcmd_screenshot(osdcmdptr_t parm) -{ - videoCaptureScreen(); - - return OSDCMD_OK; -} - -#if 0 -static int osdcmd_savestate(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_PARAMETER(parm); - G_SaveMapState(); - return OSDCMD_OK; -} - -static int osdcmd_restorestate(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_PARAMETER(parm); - G_RestoreMapState(); - return OSDCMD_OK; -} -#endif - -#ifdef DEBUGGINGAIDS -static int osdcmd_inittimer(osdcmdptr_t parm) -{ - if (parm->numparms != 1) - { - OSD_Printf("%dHz timer\n",g_timerTicsPerSecond); - return OSDCMD_SHOWHELP; - } - - G_InitTimer(Batol(parm->parms[0])); - - OSD_Printf("%s\n",parm->raw); - return OSDCMD_OK; -} -#endif - #if !defined NETCODE_DISABLE static int osdcmd_disconnect(osdcmdptr_t UNUSED(parm)) { @@ -851,13 +588,6 @@ static int osdcmd_kickban(osdcmdptr_t parm) #endif #endif -static int osdcmd_purgesaves(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - G_DeleteOldSaves(); - return OSDCMD_OK; -} - static int osdcmd_printtimes(osdcmdptr_t UNUSED(parm)) { UNREFERENCED_CONST_PARAMETER(parm); @@ -902,16 +632,12 @@ static int osdcmd_printtimes(osdcmdptr_t UNUSED(parm)) int32_t registerosdcommands(void) { - if (VOLUMEONE) - OSD_RegisterFunction("changelevel","changelevel : warps to the given level", osdcmd_changelevel); - else + if (!VOLUMEONE) { - OSD_RegisterFunction("changelevel","changelevel : warps to the given level", osdcmd_changelevel); OSD_RegisterFunction("map","map : loads the given user map", osdcmd_map); OSD_RegisterFunction("demo","demo : starts the given demo", osdcmd_demo); } - OSD_RegisterFunction("cmenu","cmenu <#>: jumps to menu", osdcmd_cmenu); OSD_RegisterFunction("crosshaircolor","crosshaircolor: changes the crosshair color", osdcmd_crosshaircolor); #if !defined NETCODE_DISABLE @@ -927,13 +653,13 @@ int32_t registerosdcommands(void) OSD_RegisterFunction("inittimer","debug", osdcmd_inittimer); #endif #if !defined NETCODE_DISABLE - //OSD_RegisterFunction("kick","kick : kicks a multiplayer client. See listplayers.", osdcmd_kick); - //OSD_RegisterFunction("kickban","kickban : kicks a multiplayer client and prevents them from reconnecting. See listplayers.", osdcmd_kickban); +#if 0 + OSD_RegisterFunction("kick","kick : kicks a multiplayer client. See listplayers.", osdcmd_kick); + OSD_RegisterFunction("kickban","kickban : kicks a multiplayer client and prevents them from reconnecting. See listplayers.", osdcmd_kickban); +#endif OSD_RegisterFunction("listplayers","listplayers: lists currently connected multiplayer clients", osdcmd_listplayers); #endif - OSD_RegisterFunction("music","music EL: change music", osdcmd_music); - OSD_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip); #if !defined NETCODE_DISABLE @@ -942,16 +668,9 @@ int32_t registerosdcommands(void) OSD_RegisterFunction("printtimes", "printtimes: prints VM timing statistics", osdcmd_printtimes); - OSD_RegisterFunction("purgesaves", "purgesaves: deletes obsolete and unreadable save files", osdcmd_purgesaves); - - OSD_RegisterFunction("quicksave","quicksave: performs a quick save", osdcmd_quicksave); - OSD_RegisterFunction("quickload","quickload: performs a quick load", osdcmd_quickload); - OSD_RegisterFunction("restartmap", "restartmap: restarts the current map", osdcmd_restartmap); OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound); - OSD_RegisterFunction("screenshot","screenshot [format]: takes a screenshot.", osdcmd_screenshot); - OSD_RegisterFunction("spawn","spawn [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",osdcmd_spawn); OSD_RegisterFunction("vidmode","vidmode : change the video mode",osdcmd_vidmode); diff --git a/source/rr/src/player.cpp b/source/rr/src/player.cpp index 6cd9c4fdc..434182de6 100644 --- a/source/rr/src/player.cpp +++ b/source/rr/src/player.cpp @@ -2758,42 +2758,10 @@ void P_GetInput(int playerNum) D_ProcessEvents(); - if (in_aimmode) - g_MyAimMode = buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - else - { - g_oldAimStat = g_myAimStat; - g_myAimStat = buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - - if (g_myAimStat > g_oldAimStat) - { - g_MyAimMode ^= 1; - P_DoQuote(QUOTE_MOUSE_AIMING_OFF + g_MyAimMode, pPlayer); - } - } + bool mouseaim = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); CONTROL_GetInput(&info); - if (in_mousedeadzone) - { - if (info.mousey > 0) - info.mousey = max(info.mousey - in_mousedeadzone, 0); - else if (info.mousey < 0) - info.mousey = min(info.mousey + in_mousedeadzone, 0); - - if (info.mousex > 0) - info.mousex = max(info.mousex - in_mousedeadzone, 0); - else if (info.mousex < 0) - info.mousex = min(info.mousex + in_mousedeadzone, 0); - } - - if (in_mousebias) - { - if (klabs(info.mousex) > klabs(info.mousey)) - info.mousey = tabledivide32_noinline(info.mousey, in_mousebias); - else - info.mousex = tabledivide32_noinline(info.mousex, in_mousebias); - } // JBF: Run key behaviour is selectable @@ -2820,7 +2788,7 @@ void P_GetInput(int playerNum) input.q16avel += fix16_from_int(info.dyaw) / analogExtent * (analogTurnAmount << 1); } - if (g_MyAimMode) + if (mouseaim) input.q16horz = fix16_div(fix16_from_int(info.mousey), F16(64)); else input.fvel = -(info.mousey >> 6); @@ -2985,7 +2953,7 @@ void P_GetInput(int playerNum) localInput.bits |= buttonMap.ButtonDown(gamefunc_Quick_Kick) << SK_QUICK_KICK; localInput.bits |= buttonMap.ButtonDown(gamefunc_TurnAround) << SK_TURNAROUND; - localInput.bits |= (g_MyAimMode << SK_AIMMODE); + localInput.bits |= (mouseaim << SK_AIMMODE); localInput.bits |= (g_gameQuit << SK_GAMEQUIT); localInput.bits |= inputState.GetKeyStatus(sc_Pause) << SK_PAUSE; localInput.bits |= ((uint32_t)inputState.GetKeyStatus(sc_Escape)) << SK_ESCAPE; @@ -3064,43 +3032,10 @@ void P_GetInputMotorcycle(int playerNum) D_ProcessEvents(); - if (in_aimmode) - g_MyAimMode = buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - else - { - g_oldAimStat = g_myAimStat; - g_myAimStat = buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - - if (g_myAimStat > g_oldAimStat) - { - g_MyAimMode ^= 1; - P_DoQuote(QUOTE_MOUSE_AIMING_OFF + g_MyAimMode, pPlayer); - } - } + bool mouseaim = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); CONTROL_GetInput(&info); - if (in_mousedeadzone) - { - if (info.mousey > 0) - info.mousey = max(info.mousey - in_mousedeadzone, 0); - else if (info.mousey < 0) - info.mousey = min(info.mousey + in_mousedeadzone, 0); - - if (info.mousex > 0) - info.mousex = max(info.mousex - in_mousedeadzone, 0); - else if (info.mousex < 0) - info.mousex = min(info.mousex + in_mousedeadzone, 0); - } - - if (in_mousebias) - { - if (klabs(info.mousex) > klabs(info.mousey)) - info.mousey = tabledivide32_noinline(info.mousey, in_mousebias); - else - info.mousex = tabledivide32_noinline(info.mousex, in_mousebias); - } - // JBF: Run key behaviour is selectable int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); constexpr int const analogTurnAmount = (NORMALTURN << 1); @@ -3362,43 +3297,10 @@ void P_GetInputBoat(int playerNum) D_ProcessEvents(); - if (in_aimmode) - g_MyAimMode = buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - else - { - g_oldAimStat = g_myAimStat; - g_myAimStat = buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - - if (g_myAimStat > g_oldAimStat) - { - g_MyAimMode ^= 1; - P_DoQuote(QUOTE_MOUSE_AIMING_OFF + g_MyAimMode, pPlayer); - } - } + bool mouseaim = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); CONTROL_GetInput(&info); - if (in_mousedeadzone) - { - if (info.mousey > 0) - info.mousey = max(info.mousey - in_mousedeadzone, 0); - else if (info.mousey < 0) - info.mousey = min(info.mousey + in_mousedeadzone, 0); - - if (info.mousex > 0) - info.mousex = max(info.mousex - in_mousedeadzone, 0); - else if (info.mousex < 0) - info.mousex = min(info.mousex + in_mousedeadzone, 0); - } - - if (in_mousebias) - { - if (klabs(info.mousex) > klabs(info.mousey)) - info.mousey = tabledivide32_noinline(info.mousey, in_mousebias); - else - info.mousex = tabledivide32_noinline(info.mousex, in_mousebias); - } - // JBF: Run key behaviour is selectable int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); constexpr int const analogTurnAmount = (NORMALTURN << 1); @@ -4540,18 +4442,18 @@ void P_FragPlayer(int playerNum) if (playerNum == screenpeek) { - Bsprintf(apStrings[QUOTE_RESERVED], "Killed by %s", &g_player[pPlayer->frag_ps].user_name[0]); + quoteMgr.InitializeQuote(QUOTE_RESERVED, "Killed by %s", &g_player[pPlayer->frag_ps].user_name[0]); P_DoQuote(QUOTE_RESERVED, pPlayer); } else { - Bsprintf(apStrings[QUOTE_RESERVED2], "Killed %s", &g_player[playerNum].user_name[0]); + quoteMgr.InitializeQuote(QUOTE_RESERVED2, "Killed %s", &g_player[playerNum].user_name[0]); P_DoQuote(QUOTE_RESERVED2, g_player[pPlayer->frag_ps].ps); } if (cl_obituaries) { - Bsprintf(tempbuf, apStrings[OBITQUOTEINDEX + (krand2() % g_numObituaries)], + Bsprintf(tempbuf, quoteMgr.GetQuote(OBITQUOTEINDEX + (krand2() % g_numObituaries)), &g_player[pPlayer->frag_ps].user_name[0], &g_player[playerNum].user_name[0]); G_AddUserQuote(tempbuf); } @@ -4564,14 +4466,14 @@ void P_FragPlayer(int playerNum) { pPlayer->fraggedself++; if ((unsigned)pPlayer->wackedbyactor < MAXTILES && A_CheckEnemyTile(sprite[pPlayer->wackedbyactor].picnum)) - Bsprintf(tempbuf, apStrings[OBITQUOTEINDEX + (krand2() % g_numObituaries)], "A monster", + Bsprintf(tempbuf, quoteMgr.GetQuote(OBITQUOTEINDEX + (krand2() % g_numObituaries)), "A monster", &g_player[playerNum].user_name[0]); else if (actor[pPlayer->i].picnum == NUKEBUTTON) Bsprintf(tempbuf, "^02%s^02 tried to leave", &g_player[playerNum].user_name[0]); else { // random suicide death string - Bsprintf(tempbuf, apStrings[SUICIDEQUOTEINDEX + (krand2() % g_numSelfObituaries)], + Bsprintf(tempbuf, quoteMgr.GetQuote(SUICIDEQUOTEINDEX + (krand2() % g_numSelfObituaries)), &g_player[playerNum].user_name[0]); } } diff --git a/source/rr/src/premap.cpp b/source/rr/src/premap.cpp index b7f4b9316..3a98f6808 100644 --- a/source/rr/src/premap.cpp +++ b/source/rr/src/premap.cpp @@ -28,6 +28,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "savegame.h" #include "cmdline.h" #include "statistics.h" +#include "menu/menu.h" +#include "mapinfo.h" +#include "cmdlib.h" BEGIN_RR_NS @@ -35,6 +38,7 @@ static int32_t g_whichPalForPlayer = 9; static uint8_t precachehightile[2][MAXTILES>>3]; static int32_t g_precacheCount; +int32_t g_skillSoundVoice = -1; static void flag_precache(int32_t tile, int32_t type) @@ -494,7 +498,7 @@ static void G_DoLoadScreen(const char *statustext, int32_t percent) if (boardfilename[0] != 0 && ud.level_number == 7 && ud.volume_number == 0) { - menutext_center(textY, RR ? "ENTERIN' USER MAP" : "Loading User Map"); + menutext_center(textY, RR ? GStrings("TXT_ENTRUM") : GStrings("TXT_LOADUM")); if (RR) menutext_center(textY+20, boardfilename); else @@ -502,14 +506,13 @@ static void G_DoLoadScreen(const char *statustext, int32_t percent) } else if (RR && g_lastLevel) { - menutext_center(textY,"ENTERIN'"); - menutext_center(textY+16+8,"CLOSE ENCOUNTERS"); + menutext_center(textY,GStrings("TXT_ENTERIN")); + menutext_center(textY+16+8,GStrings("TXT_CLOSEENCOUNTERS")); } else { - menutext_center(textY, RR ? "ENTERIN'" : "Loading"); - if (g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name != NULL) - menutext_center(textY+16+8,g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name); + menutext_center(textY, RR ? GStrings("TXT_ENTERIN") : GStrings("TXT_LOADING")); + menutext_center(textY+16+8,mapList[(ud.volume_number*MAXLEVELS) + ud.level_number].DisplayName()); } #ifndef EDUKE32_TOUCH_DEVICES @@ -546,7 +549,7 @@ static void G_DoLoadScreen(const char *statustext, int32_t percent) rotatesprite_fs(320<<15,200<<15,65536L, 0,LOADSCREEN,0,0,2+8+64+BGSTRETCH); - menutext_center(RRRA?155:105,RR?"LOADIN'":"Loading..."); + menutext_center(RRRA?155:105,RR? GStrings("TXT_LOADIN") : GStrings("TXT_Loading...")); if (statustext) gametext_center_number(180, statustext); videoNextPage(); } @@ -641,7 +644,6 @@ void G_CacheMapData(void) { Bsprintf(tempbuf, "Loaded %d%% (%d/%d textures)\n", lpc, pc, g_precacheCount); G_DoLoadScreen(tempbuf, lpc); - timerUpdate(); if (totalclock - tc >= 1) { @@ -1900,14 +1902,9 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum) ud.player_skill = skillNum; ud.secretlevel = 0; ud.from_bonus = 0; - STAT_StartNewGame(g_volumeNames[volumeNum], skillNum); ud.last_level = -1; - g_lastAutoSaveArbitraryID = -1; - g_lastautosave.reset(); - g_lastusersave.reset(); - g_quickload = nullptr; - + int const UserMap = Menu_HaveUserMap(); // we don't want the intro to play after the multiplayer setup screen @@ -1947,7 +1944,7 @@ end_vol4a: pPlayer->zoom = 768; #endif pPlayer->gm = 0; - Menu_Close(0); + M_ClearMenus(); //AddLog("Newgame"); @@ -2183,10 +2180,7 @@ int G_FindLevelByFile(const char *fileName) for (bssize_t levelNum = 0; levelNum < MAXLEVELS; levelNum++) { - if (g_mapInfo[volOffset + levelNum].filename == NULL) - continue; - - if (!Bstrcasecmp(fileName, g_mapInfo[volOffset + levelNum].filename)) + if (!mapList[volOffset + levelNum].fileName.CompareNoCase(fileName)) return volOffset + levelNum; } } @@ -2249,24 +2243,22 @@ static void G_LoadMapHack(char *outbuf, const char *filename) } // levnamebuf should have at least size BMAX_PATH -void G_SetupFilenameBasedMusic(char *nameBuf, const char *fileName, int levelNum) +void G_SetupFilenameBasedMusic(char *nameBuf, const char *fileName) { char *p; char const *exts[] = { -#ifdef HAVE_FLAC "flac", -#endif -#ifdef HAVE_VORBIS "ogg", -#endif -#ifdef HAVE_XMP + "mp3", "xm", "mod", "it", "s3m", "mtm", -#endif - "mid" + "mid", + "hmp", + "hmi", + "xmi" }; Bstrncpy(nameBuf, fileName, BMAX_PATH); @@ -2283,14 +2275,14 @@ void G_SetupFilenameBasedMusic(char *nameBuf, const char *fileName, int levelNum { Bmemcpy(p+1, ext, Bstrlen(ext) + 1); - if (testkopen(nameBuf, 0)) - { - realloc_copy(&g_mapInfo[levelNum].musicfn, nameBuf); + if (FileExists(nameBuf)) + { + userMapRecord.music = nameBuf; return; } } - realloc_copy(&g_mapInfo[levelNum].musicfn, "dethtoll.mid"); + userMapRecord.music = "dethtoll.mid"; } int G_EnterLevel(int gameMode) @@ -2345,35 +2337,21 @@ int G_EnterLevel(int gameMode) } } - mii = (ud.volume_number*MAXLEVELS)+ud.level_number; + // Redirect the final RR level to a valid map record so that currentLevel can point to something. + mii = (RR && g_lastLevel)? 127 : (ud.volume_number*MAXLEVELS)+ud.level_number; + auto &mi = mapList[mii]; - if (g_mapInfo[mii].name == NULL || g_mapInfo[mii].filename == NULL) + if (mi.fileName.IsEmpty() && !Menu_HaveUserMap()) { - if (RR && g_lastLevel) - { - if (g_mapInfo[mii].filename == NULL) - g_mapInfo[mii].filename = (char *)Xcalloc(BMAX_PATH, sizeof(uint8_t)); - if (g_mapInfo[mii].name == NULL) - g_mapInfo[mii].name = Xstrdup("CLOSE ENCOUNTERS"); - } - else if (Menu_HaveUserMap()) - { - if (g_mapInfo[mii].filename == NULL) - g_mapInfo[mii].filename = (char *)Xcalloc(BMAX_PATH, sizeof(uint8_t)); - if (g_mapInfo[mii].name == NULL) - g_mapInfo[mii].name = Xstrdup("User Map"); - } - else - { - OSD_Printf(OSDTEXT_RED "Map E%dL%d not defined!\n", ud.volume_number+1, ud.level_number+1); - return 1; - } + OSD_Printf(OSDTEXT_RED "Map E%dL%d not defined!\n", ud.volume_number+1, ud.level_number+1); + return 1; } i = ud.screen_size; ud.screen_size = 0; - G_DoLoadScreen("Loading map . . .", -1); + FStringf msg("%s . . .", GStrings("TXT_LOADMAP")); + G_DoLoadScreen(msg, -1); G_UpdateScreenArea(); ud.screen_size = i; @@ -2381,38 +2359,30 @@ int G_EnterLevel(int gameMode) DukePlayer_t *const pPlayer = g_player[0].ps; int16_t lbang; - if (RR && g_lastLevel) - { - if (engineLoadBoard("endgame.map", 0, &pPlayer->pos, &lbang, &pPlayer->cursectnum) < 0) - { - OSD_Printf(OSD_ERROR "Map \"endgame.map\" not found or invalid map version!\n"); - return 1; - } - - G_LoadMapHack(levelName, "endgame.map"); - G_SetupFilenameBasedMusic(levelName, "endgame.map", m_level_number); - } - else if (!VOLUMEONE && Menu_HaveUserMap()) + if (!VOLUMEONE && Menu_HaveUserMap()) { if (engineLoadBoard(boardfilename, 0, &pPlayer->pos, &lbang, &pPlayer->cursectnum) < 0) { OSD_Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", boardfilename); return 1; } - - STAT_NewLevel(boardfilename); + userMapRecord.name = ""; + userMapRecord.SetFileName(boardfilename); + currentLevel = &userMapRecord; + STAT_NewLevel(boardfilename); G_LoadMapHack(levelName, boardfilename); - G_SetupFilenameBasedMusic(levelName, boardfilename, m_level_number); + G_SetupFilenameBasedMusic(levelName, boardfilename); } - else if (engineLoadBoard(g_mapInfo[mii].filename, VOLUMEONE, &pPlayer->pos, &lbang, &pPlayer->cursectnum) < 0) + else if (engineLoadBoard(mi.fileName, VOLUMEONE, &pPlayer->pos, &lbang, &pPlayer->cursectnum) < 0) { - OSD_Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", g_mapInfo[mii].filename); + OSD_Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", mi.fileName.GetChars()); return 1; } else { - STAT_NewLevel(g_mapInfo[mii].filename); - G_LoadMapHack(levelName, g_mapInfo[mii].filename); + currentLevel = &mi; + STAT_NewLevel(mi.fileName); + G_LoadMapHack(levelName, mi.fileName); } if (RR && !RRRA && ud.volume_number == 1 && ud.level_number == 1) @@ -2447,7 +2417,7 @@ int G_EnterLevel(int gameMode) G_AlignWarpElevators(); resetpspritevars(gameMode); - ud.playerbest = CONFIG_GetMapBestTime(Menu_HaveUserMap() ? boardfilename : g_mapInfo[mii].filename, g_loadedMapHack.md4); + ud.playerbest = CONFIG_GetMapBestTime(Menu_HaveUserMap() ? boardfilename : mi.fileName.GetChars(), g_loadedMapHack.md4); // G_FadeLoad(0,0,0, 252,0, -28, 4, -1); G_CacheMapData(); @@ -2455,14 +2425,7 @@ int G_EnterLevel(int gameMode) if (ud.recstat != 2) { - if (g_mapInfo[g_musicIndex].musicfn == NULL || - g_mapInfo[mii].musicfn == NULL || // intentional, to pass control further while avoiding the strcmp on null - strcmp(g_mapInfo[g_musicIndex].musicfn, g_mapInfo[mii].musicfn) || - g_musicSize == 0 || - ud.last_level == -1) - { - S_PlayLevelMusicOrNothing(mii); - } + S_PlayLevelMusicOrNothing(mii); } if (RR && !(gameMode & MODE_DEMO)) @@ -2473,7 +2436,6 @@ int G_EnterLevel(int gameMode) for (TRAVERSE_CONNECT(i)) { g_player[i].ps->gm = MODE_GAME; - Menu_Close(i); } } else if (gameMode & MODE_RESTART) @@ -2540,16 +2502,15 @@ int G_EnterLevel(int gameMode) //AddLog(g_szBuf); // variables are set by pointer... - Bmemcpy(currentboardfilename, boardfilename, BMAX_PATH); if (G_HaveUserMap()) { - OSD_Printf(OSDTEXT_YELLOW "User Map: %s\n", boardfilename); + OSD_Printf(OSDTEXT_YELLOW "%s: %s\n", GStrings("TXT_USERMAP"), boardfilename); } else { OSD_Printf(OSDTEXT_YELLOW "E%dL%d: %s\n", ud.volume_number+1, ud.level_number+1, - g_mapInfo[mii].name); + mapList[mii].DisplayName()); } g_restorePalette = -1; diff --git a/source/rr/src/quotes.h b/source/rr/src/quotes.h index 4ff44df24..46858c821 100644 --- a/source/rr/src/quotes.h +++ b/source/rr/src/quotes.h @@ -23,8 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef quotes_h_ #define quotes_h_ -#define MAXQUOTES 16384 -#define MAXQUOTELEN 128 +#include "quotemgr.h" + #define OBITQUOTEINDEX (MAXQUOTES-128) #define SUICIDEQUOTEINDEX (MAXQUOTES-32) diff --git a/source/rr/src/savegame.cpp b/source/rr/src/savegame.cpp index 0501c6f7a..4059ca312 100644 --- a/source/rr/src/savegame.cpp +++ b/source/rr/src/savegame.cpp @@ -28,8 +28,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "i_specialpaths.h" #include "gamecontrol.h" #include "version.h" -#include "statistics.h" -#include "secrets.h" +#include "z_music.h" +#include "mapinfo.h" + #include "savegamehelp.h" BEGIN_RR_NS @@ -138,16 +139,6 @@ void G_ResetInterpolations(void) G_SetInterpolation(g_animatePtr[i]); } -savebrief_t g_lastautosave, g_lastusersave, g_freshload; -int32_t g_lastAutoSaveArbitraryID = -1; -bool g_saveRequested; -savebrief_t * g_quickload; - -menusave_t * g_menusaves; -uint16_t g_nummenusaves; - -static menusave_t * g_internalsaves; -static uint16_t g_numinternalsaves; static FileReader *OpenSavegame(const char *fn) { @@ -155,13 +146,7 @@ static FileReader *OpenSavegame(const char *fn) { return nullptr; } - auto file = ReadSavegameChunk("DEMOLITION_RN"); - if (!file.isOpen()) - { - FinishSavegameRead(); - return nullptr; - } - file = ReadSavegameChunk("snapshot.dat"); + auto file = ReadSavegameChunk("snapshot.dat"); if (!file.isOpen()) { FinishSavegameRead(); @@ -170,130 +155,9 @@ static FileReader *OpenSavegame(const char *fn) return new FileReader(std::move(file)); } -static void ReadSaveGameHeaders_CACHE1D(TArray& saves) -{ - savehead_t h; - - for (FString &save : saves) - { - auto fil = OpenSavegame(save); - if (!fil) - continue; - - menusave_t & msv = g_internalsaves[g_numinternalsaves]; - - int32_t k = sv_loadheader(*fil, 0, &h); - delete fil; - if (k) - { - if (k < 0) - msv.isUnreadable = 1; - msv.isOldVer = 1; - } - else - msv.isOldVer = 0; - - msv.isAutoSave = h.isAutoSave(); - - strncpy(msv.brief.path, save.GetChars(), ARRAY_SIZE(msv.brief.path)); - ++g_numinternalsaves; - - if (k >= 0 && h.savename[0] != '\0') - { - memcpy(msv.brief.name, h.savename, ARRAY_SIZE(msv.brief.name)); - } - else - msv.isUnreadable = 1; - } - FinishSavegameRead(); -} - -static void ReadSaveGameHeaders_Internal(void) -{ - FString pattern = M_GetSavegamesPath() + "*.bsv"; - TArray saves; - D_AddWildFile(saves, pattern); - - // potentially overallocating but programmatically simple - int const numfiles = saves.Size(); - size_t const internalsavesize = sizeof(menusave_t) * numfiles; - - g_internalsaves = (menusave_t *)Xrealloc(g_internalsaves, internalsavesize); - - for (int x = 0; x < numfiles; ++x) - g_internalsaves[x].clear(); - - g_numinternalsaves = 0; - ReadSaveGameHeaders_CACHE1D(saves); - - g_nummenusaves = 0; - for (int x = g_numinternalsaves-1; x >= 0; --x) - { - menusave_t & msv = g_internalsaves[x]; - if (!msv.isUnreadable) - { - ++g_nummenusaves; - } - } - size_t const menusavesize = sizeof(menusave_t) * g_nummenusaves; - - g_menusaves = (menusave_t *)Xrealloc(g_menusaves, menusavesize); - - for (int x = 0; x < g_nummenusaves; ++x) - g_menusaves[x].clear(); - - for (int x = g_numinternalsaves-1, y = 0; x >= 0; --x) - { - menusave_t & msv = g_internalsaves[x]; - if (!msv.isUnreadable) - { - g_menusaves[y++] = msv; - } - } - - for (int x = g_numinternalsaves-1; x >= 0; --x) - { - char const * const path = g_internalsaves[x].brief.path; - int const pathlen = Bstrlen(path); - if (pathlen < 12) - continue; - char const * const fn = path + (pathlen-12); - if (fn[0] == 's' && fn[1] == 'a' && fn[2] == 'v' && fn[3] == 'e' && - isdigit(fn[4]) && isdigit(fn[5]) && isdigit(fn[6]) && isdigit(fn[7])) - { - char number[5]; - memcpy(number, fn+4, 4); - number[4] = '\0'; - savecounter.count = Batoi(number)+1; - break; - } - } -} void ReadSaveGameHeaders(void) { - ReadSaveGameHeaders_Internal(); - - if (!cl_autosavedeletion) - return; - - bool didDelete = false; - int numautosaves = 0; - for (int x = 0; x < g_nummenusaves; ++x) - { - menusave_t & msv = g_menusaves[x]; - if (!msv.isAutoSave) - continue; - if (numautosaves >= cl_maxautosaves) - { - G_DeleteSave(msv.brief); - didDelete = true; - } - ++numautosaves; - } - - if (didDelete) - ReadSaveGameHeaders_Internal(); } int32_t G_LoadSaveHeaderNew(char const *fn, savehead_t *saveh) @@ -307,24 +171,6 @@ int32_t G_LoadSaveHeaderNew(char const *fn, savehead_t *saveh) if (i < 0) goto corrupt; - ssfil = ReadSavegameChunk("screenshot.dat"); - - TileFiles.tileCreate(TILE_LOADSHOT, 200, 320); - if (ssfil.isOpen()) - { - if (ssfil.Read(tileData(TILE_LOADSHOT), 320 * 200) != 320 * 200) - { - OSD_Printf("G_LoadSaveHeaderNew(): failed reading screenshot in \"%s\"\n", fn); - goto corrupt; - } - } - else - { - Bmemset(tileData(TILE_LOADSHOT), 0, 320*200); - } - ssfil.Close(); - tileInvalidate(TILE_LOADSHOT, 0, 255); - delete fil; FinishSavegameRead(); return 0; @@ -338,13 +184,11 @@ corrupt: static void sv_postudload(); -// hack -static int different_user_map; // XXX: keyboard input 'blocked' after load fail? (at least ESC?) -int32_t G_LoadPlayer(savebrief_t & sv) +int32_t G_LoadPlayer(const char *path) { - auto fil = OpenSavegame(sv.path); + auto fil = OpenSavegame(path); if (!fil) return -1; @@ -371,6 +215,7 @@ int32_t G_LoadPlayer(savebrief_t & sv) // some setup first ud.multimode = h.numplayers; + S_PauseSounds(true); if (numplayers > 1) { @@ -393,33 +238,25 @@ int32_t G_LoadPlayer(savebrief_t & sv) ud.m_player_skill = h.skill; // NOTE: Bmemcpy needed for SAVEGAME_MUSIC. - EDUKE32_STATIC_ASSERT(sizeof(boardfilename) == sizeof(h.boardfn)); - different_user_map = Bstrcmp(boardfilename, h.boardfn); - Bmemcpy(boardfilename, h.boardfn, sizeof(boardfilename)); + strcpy(boardfilename, currentLevel->fileName); - int const mapIdx = h.volnum*MAXLEVELS + h.levnum; + char workbuffer[BMAX_PATH]; + Bstrcpy(workbuffer, currentLevel->fileName); - if (boardfilename[0]) - Bstrcpy(currentboardfilename, boardfilename); - else if (g_mapInfo[mapIdx].filename) - Bstrcpy(currentboardfilename, g_mapInfo[mapIdx].filename); - - if (currentboardfilename[0]) + if (workbuffer[0]) { - artSetupMapArt(currentboardfilename); - append_ext_UNSAFE(currentboardfilename, ".mhk"); - engineLoadMHK(currentboardfilename); + artSetupMapArt(workbuffer); + append_ext_UNSAFE(workbuffer, ".mhk"); + engineLoadMHK(workbuffer); } - Bmemcpy(currentboardfilename, boardfilename, BMAX_PATH); - if (status == 2) G_NewGame_EnterLevel(); - else if ((status = sv_loadsnapshot(*fil, 0, &h)) || !ReadStatistics() || !SECRET_Load()) // read the rest... + else if ((status = sv_loadsnapshot(*fil, 0, &h))) // read the rest... { // in theory, we could load into an initial dump first and trivially // recover if things go wrong... - Bsprintf(tempbuf, "Loading save game file \"%s\" failed (code %d), cannot recover.", sv.path, status); + Bsprintf(tempbuf, "Loading save game file \"%s\" failed (code %d), cannot recover.", path, status); G_GameExit(tempbuf); } @@ -447,66 +284,14 @@ static void G_SaveTimers(void) static void G_RestoreTimers(void) { - timerUpdate(); - totalclock = g_timers.totalclock; totalclocklock = g_timers.totalclocklock; ototalclock = g_timers.ototalclock; lockclock = g_timers.lockclock; } -////////// - - -void G_DeleteSave(savebrief_t const & sv) +bool G_SavePlayer(FSaveGameNode *sv) { - if (!sv.isValid()) - return; - - char temp[BMAX_PATH]; - - if (snprintf(temp, sizeof(temp), "%s%s", M_GetSavegamesPath().GetChars(), sv.path)) - { - OSD_Printf("G_SavePlayer: file name \"%s\" too long\n", sv.path); - return; - } - - remove(temp); -} - -void G_DeleteOldSaves(void) -{ - ReadSaveGameHeaders(); - - for (int x = 0; x < g_numinternalsaves; ++x) - { - menusave_t const & msv = g_internalsaves[x]; - if (msv.isOldVer || msv.isUnreadable) - G_DeleteSave(msv.brief); - } -} - -uint16_t G_CountOldSaves(void) -{ - ReadSaveGameHeaders(); - - int bad = 0; - for (int x = 0; x < g_numinternalsaves; ++x) - { - menusave_t const & msv = g_internalsaves[x]; - if (msv.isOldVer || msv.isUnreadable) - ++bad; - } - - return bad; -} - -int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave) -{ -#ifdef __ANDROID__ - G_SavePalette(); -#endif - G_SaveTimers(); Net_WaitForEverybody(); @@ -517,66 +302,27 @@ int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave) errno = 0; FileWriter *fil; - if (sv.isValid()) + OpenSaveGameForWrite(sv->Filename); + fil = WriteSavegameChunk("snapshot.dat"); + // The above call cannot fail. { - fn.Format("%s%s", M_GetSavegamesPath().GetChars(), sv.path); - OpenSaveGameForWrite(fn); - fil = WriteSavegameChunk("snapshot.dat"); - } - else - { - static char const SaveName[] = "save0000.bsv"; - fn.Format("%s%s", M_GetSavegamesPath().GetChars(), SaveName); - - auto fnp = fn.LockBuffer(); - char* zeros = fnp + (fn.Len() - 8); - fil = savecounter.opennextfile(fnp, zeros); - if (fil) - { - delete fil; - remove(fnp); - OpenSaveGameForWrite(fnp); - fil = WriteSavegameChunk("snapshot.dat"); - } - fn.UnlockBuffer(); - savecounter.count++; - // don't copy the mod dir into sv.path - Bstrcpy(sv.path, fn + (fn.Len() - (ARRAY_SIZE(SaveName) - 1))); - } - - if (!fil) - { - OSD_Printf("G_SavePlayer: failed opening \"%s\" for writing: %s\n", - fn.GetChars(), strerror(errno)); - ready2send = 1; - Net_WaitForEverybody(); - - G_RestoreTimers(); - ototalclock = totalclock; - return -1; - } - else - { - WriteSavegameChunk("DEMOLITION_RN"); auto& fw = *fil; - //CompressedFileWriter fw(fil, true); // temporary hack ud.user_map = G_HaveUserMap(); // SAVE! - sv_saveandmakesnapshot(fw, sv.name, 0, 0, 0, 0, isAutoSave); - SaveStatistics(); - SECRET_Save(); + sv_saveandmakesnapshot(fw, sv->SaveTitle, 0, 0); + fw.Close(); - FinishSavegameWrite(); + bool res = FinishSavegameWrite(); if (!g_netServer && ud.multimode < 2) { OSD_Printf("Saved: %s\n", fn.GetChars()); - Bstrcpy(apStrings[QUOTE_RESERVED4], "Game Saved"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "Game Saved"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); } @@ -586,39 +332,46 @@ int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave) G_RestoreTimers(); ototalclock = totalclock; - return 0; + return res; } } -int32_t G_LoadPlayerMaybeMulti(savebrief_t & sv) +bool GameInterface::LoadGame(FSaveGameNode* sv) { if (g_netServer || ud.multimode > 1) { - Bstrcpy(apStrings[QUOTE_RESERVED4], "Multiplayer Loading Not Yet Supported"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "Multiplayer Loading Not Yet Supported"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); // g_player[myconnectindex].ps->gm = MODE_GAME; - return 127; + return false; } else { - int32_t c = G_LoadPlayer(sv); + int32_t c = G_LoadPlayer(sv->Filename); if (c == 0) g_player[myconnectindex].ps->gm = MODE_GAME; - return c; + return !c; } } -void G_SavePlayerMaybeMulti(savebrief_t & sv, bool isAutoSave) +bool GameInterface::SaveGame(FSaveGameNode* sv) { if (g_netServer || ud.multimode > 1) { - Bstrcpy(apStrings[QUOTE_RESERVED4], "Multiplayer Saving Not Yet Supported"); + quoteMgr.InitializeQuote(QUOTE_RESERVED4, "Multiplayer Saving Not Yet Supported"); P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps); + return false; } else { - G_SavePlayer(sv, isAutoSave); + + videoNextPage(); // no idea if this is needed here. + g_screenCapture = 1; + G_DrawRooms(myconnectindex, 65536); + g_screenCapture = 0; + + return G_SavePlayer(sv); } } @@ -632,11 +385,6 @@ typedef struct dataspec_ intptr_t cnt; } dataspec_t; -#define SV_DEFAULTCOMPRTHRES 8 -static uint8_t savegame_diffcompress; // 0:none, 1:Ken's LZW in cache1d.c -static uint8_t savegame_comprthres; - - #define DS_DYNAMIC 1 // dereference .ptr one more time #define DS_STRING 2 #define DS_CMP 4 @@ -784,8 +532,8 @@ static int32_t readspecdata(const dataspec_t *spec, FileReader *fil, uint8_t **d if (ksiz != siz) { OSD_Printf("rsd: spec=%s, idx=%d, mem=%p\n", (char *)sptr->ptr, (int32_t)(spec - sptr), mem); - OSD_Printf(" (%s): read %d, expected %d!\n", - ((spec->flags & DS_CNTMASK) == 0 && spec->size * cnt <= savegame_comprthres) ? "uncompressed" : "compressed", ksiz, siz); + OSD_Printf(" : read %d, expected %d!\n", + ksiz, siz); if (ksiz == -1) OSD_Printf(" read: %s\n", strerror(errno)); @@ -1088,8 +836,6 @@ static void sv_rrrafog(); ((sizeof(g_player[0].user_name)+sizeof(g_player[0].pcolor)+sizeof(g_player[0].pteam) \ +sizeof(g_player[0].frags)+sizeof(DukePlayer_t))*MAXPLAYERS) -static uint8_t savegame_quotedef[MAXQUOTES>>3]; -static char (*savegame_quotes)[MAXQUOTELEN]; static uint8_t savegame_restdata[SVARDATALEN]; static char svgm_udnetw_string [] = "blK:udnt"; @@ -1122,8 +868,6 @@ static const dataspec_t svgm_udnetw[] = { DS_NOCHK, &ud.noexits, sizeof(ud.noexits), 1 }, { DS_NOCHK, &ud.playerai, sizeof(ud.playerai), 1 }, { 0, &ud.pause_on, sizeof(ud.pause_on), 1 }, - { DS_NOCHK, ¤tboardfilename[0], BMAX_PATH, 1 }, -// { DS_LOADFN, (void *)&sv_postudload, 0, 1 }, { 0, connectpoint2, sizeof(connectpoint2), 1 }, { 0, &randomseed, sizeof(randomseed), 1 }, { 0, &g_globalRandom, sizeof(g_globalRandom), 1 }, @@ -1289,12 +1033,6 @@ static const dataspec_t svgm_anmisc[] = { 0, &g_fogType, sizeof(g_fogType), 1 }, { DS_LOADFN, (void *)sv_rrrafog, 0, 1 }, - { DS_SAVEFN|DS_LOADFN|DS_NOCHK, (void *)sv_prequote, 0, 1 }, - { DS_SAVEFN, (void *)&sv_quotesave, 0, 1 }, - { DS_NOCHK, &savegame_quotedef, sizeof(savegame_quotedef), 1 }, // quotes can change during runtime, but new quote numbers cannot be allocated - { DS_DYNAMIC, &savegame_quotes, MAXQUOTELEN, MAXQUOTES }, - { DS_LOADFN, (void *)&sv_quoteload, 0, 1 }, - { DS_SAVEFN, (void *)&sv_restsave, 0, 1 }, { 0, savegame_restdata, 1, sizeof(savegame_restdata) }, // sz/cnt swapped for kdfread { DS_LOADFN, (void *)&sv_restload, 0, 1 }, @@ -1335,14 +1073,10 @@ static void SV_AllocSnap(int32_t allocinit) } // make snapshot only if spot < 0 (demo) -int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress, bool isAutoSave) +int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, bool isAutoSave) { savehead_t h; - // set a few savegame system globals - savegame_comprthres = SV_DEFAULTCOMPRTHRES; - savegame_diffcompress = diffcompress; - // calculate total snapshot size svsnapsiz = calcsz(svgm_udnetw) + calcsz(svgm_secwsp) + calcsz(svgm_script) + calcsz(svgm_anmisc); @@ -1359,10 +1093,6 @@ int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, i h.bytever = BYTEVERSION; h.userbytever = ud.userbytever; h.scriptcrc = g_scriptcrc; - h.comprthres = savegame_comprthres; - h.recdiffsp = recdiffsp; - h.diffcompress = savegame_diffcompress; - h.synccompress = synccompress; h.reccnt = 0; h.snapsiz = svsnapsiz; @@ -1375,40 +1105,35 @@ int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, i h.levnum = ud.level_number; h.skill = ud.player_skill; - const uint32_t BSZ = sizeof(h.boardfn); - EDUKE32_STATIC_ASSERT(BSZ == sizeof(currentboardfilename)); - Bstrncpy(h.boardfn, currentboardfilename, BSZ); - if (spot >= 0) { // savegame - Bstrncpyz(h.savename, name, sizeof(h.savename)); auto fw = WriteSavegameChunk("header.dat"); fw->Write(&h, sizeof(savehead_t)); + G_WriteSaveHeader(name); } else { // demo - + // demo (currently broken, needs a new format.) const time_t t = time(NULL); - struct tm * st; - - Bstrncpyz(h.savename, "EDuke32 demo", sizeof(h.savename)); - if (t>=0 && (st = localtime(&t))) - Bsnprintf(h.savename, sizeof(h.savename), "Demo %04d%02d%02d %s", - st->tm_year+1900, st->tm_mon+1, st->tm_mday, GetGitDescription()); + struct tm * st = localtime(&t); + FStringf demoname("Demo %04d%02d%02d %s", st->tm_year+1900, st->tm_mon+1, st->tm_mday, GetGitDescription()); fil.Write(&h, sizeof(savehead_t)); + } // write header +#if 0 // not usable anymore if (spot >= 0 && tileData(TILE_SAVESHOT)) { auto fw = WriteSavegameChunk("screenshot.dat"); fw->Write(tileData(TILE_SAVESHOT), 320*200); } +#endif if (spot >= 0) @@ -1521,8 +1246,6 @@ int32_t sv_loadsnapshot(FileReader &fil, int32_t spot, savehead_t *h) OSD_Printf("sv_loadsnapshot: snapshot size: %d bytes.\n", h->snapsiz); #endif - savegame_comprthres = h->comprthres; - if (spot >= 0) { // savegame @@ -1535,9 +1258,6 @@ int32_t sv_loadsnapshot(FileReader &fil, int32_t spot, savehead_t *h) } else { - // demo - savegame_diffcompress = h->diffcompress; - svsnapsiz = h->snapsiz; SV_AllocSnap(1); @@ -1624,7 +1344,6 @@ int32_t sv_readdiff(FileReader &fil) // SVGM data description static void sv_postudload() { -// Bmemcpy(&boardfilename[0], ¤tboardfilename[0], BMAX_PATH); // DON'T do this in demos! #if 1 m_level_number = ud.level_number; ud.m_volume_number = ud.volume_number; @@ -1686,33 +1405,6 @@ static void sv_postanimateptr() { G_Util_PtrToIdx(g_animatePtr, g_animateCnt, sector, P2I_BACK); } -static void sv_prequote() -{ - if (!savegame_quotes) - { - void *ptr = Xcalloc(MAXQUOTES, MAXQUOTELEN); - savegame_quotes = (char(*)[MAXQUOTELEN])ptr; - } -} -static void sv_quotesave() -{ - Bmemset(savegame_quotedef, 0, sizeof(savegame_quotedef)); - for (int i = 0; i < MAXQUOTES; i++) - if (apStrings[i]) - { - savegame_quotedef[i>>3] |= 1<<(i&7); - Bmemcpy(savegame_quotes[i], apStrings[i], MAXQUOTELEN); - } -} -static void sv_quoteload() -{ - for (int i = 0; i < MAXQUOTES; i++) - if (savegame_quotedef[i>>3] & (1<<(i&7))) - { - C_AllocQuote(i); - Bmemcpy(apStrings[i], savegame_quotes[i], MAXQUOTELEN); - } -} static void sv_restsave() { uint8_t * mem = savegame_restdata; @@ -1850,27 +1542,11 @@ static void postloadplayer(int32_t savegamep) //2.5 if (savegamep) { - int32_t musicIdx = (ud.music_episode*MAXLEVELS) + ud.music_level; - Bmemset(gotpic, 0, sizeof(gotpic)); S_ClearSoundLocks(); G_CacheMapData(); - - if (boardfilename[0] != 0 && ud.level_number == 7 && ud.volume_number == 0 && ud.music_level == 7 && ud.music_episode == 0) - { - char levname[BMAX_PATH]; - G_SetupFilenameBasedMusic(levname, boardfilename, ud.level_number); - } - - if (g_mapInfo[musicIdx].musicfn != NULL && (musicIdx != g_musicIndex || different_user_map)) - { - ud.music_episode = g_musicIndex / MAXLEVELS; - ud.music_level = g_musicIndex % MAXLEVELS; - S_PlayLevelMusicOrNothing(musicIdx); - } - - if (MusicEnabled()) - S_PauseMusic(false); + MUS_ResumeSaved(); + Mus_SetPaused(false); g_player[myconnectindex].ps->gm = MODE_GAME; ud.recstat = 0; diff --git a/source/rr/src/savegame.h b/source/rr/src/savegame.h index d4f912af6..9feb8950e 100644 --- a/source/rr/src/savegame.h +++ b/source/rr/src/savegame.h @@ -41,91 +41,28 @@ typedef struct uint32_t userbytever; uint32_t scriptcrc; - uint8_t comprthres; - uint8_t recdiffsp, diffcompress, synccompress; + uint8_t recdiffsp; // 4 bytes int32_t reccnt, snapsiz; // 8 bytes - char savename[MAXSAVEGAMENAMESTRUCT]; uint8_t numplayers, volnum, levnum, skill; - char boardfn[BMAX_PATH]; // 286 bytes -#ifdef __ANDROID__ - char skillname[32], volname[32]; -#endif - uint8_t getPtrSize() const { return ptrsize & 0x7Fu; } - bool isAutoSave() const { return !!(ptrsize & (1u<<7u)); } + uint8_t getPtrSize() const { return ptrsize; } } savehead_t; #pragma pack(pop) -struct savebrief_t -{ - savebrief_t() - { - reset(); - } - savebrief_t(char const *n) - { - strncpy(name, n, MAXSAVEGAMENAME); - path[0] = '\0'; - } - - char name[MAXSAVEGAMENAMESTRUCT]; - char path[BMAX_PATH]; - - void reset() - { - name[0] = '\0'; - path[0] = '\0'; - } - bool isValid() const - { - return path[0] != '\0'; - } -}; - -struct menusave_t -{ - savebrief_t brief; - uint8_t isOldVer = 0; - uint8_t isUnreadable = 0; - uint8_t isAutoSave = 0; - void clear() - { - brief.reset(); - isOldVer = 0; - isUnreadable = 0; - isAutoSave = 0; - } -}; - -extern savebrief_t g_lastautosave, g_lastusersave, g_freshload; -extern int32_t g_lastAutoSaveArbitraryID; -extern bool g_saveRequested; -extern savebrief_t * g_quickload; - -extern menusave_t * g_menusaves; -extern uint16_t g_nummenusaves; - int32_t sv_updatestate(int32_t frominit); int32_t sv_readdiff(FileReader& fil); uint32_t sv_writediff(FileWriter *fil); int32_t sv_loadheader(FileReader &fil, int32_t spot, savehead_t *h); int32_t sv_loadsnapshot(FileReader &fil, int32_t spot, savehead_t *h); -int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, int8_t recdiffsp, int8_t diffcompress, int8_t synccompress, bool isAutoSave = false); +int32_t sv_saveandmakesnapshot(FileWriter &fil, char const *name, int8_t spot, bool isAutoSave = false); void sv_freemem(); -void G_DeleteSave(savebrief_t const & sv); -void G_DeleteOldSaves(void); -uint16_t G_CountOldSaves(void); -int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave); -int32_t G_LoadPlayer(savebrief_t & sv); int32_t G_LoadSaveHeaderNew(char const *fn, savehead_t *saveh); void ReadSaveGameHeaders(void); -void G_SavePlayerMaybeMulti(savebrief_t & sv, bool isAutoSave = false); -int32_t G_LoadPlayerMaybeMulti(savebrief_t & sv); #ifdef YAX_ENABLE extern void sv_postyaxload(void); diff --git a/source/rr/src/sbar.cpp b/source/rr/src/sbar.cpp index 3361575f5..a3c31c67e 100644 --- a/source/rr/src/sbar.cpp +++ b/source/rr/src/sbar.cpp @@ -982,12 +982,12 @@ void G_DrawStatusBar(int32_t snum) G_DrawInvNum(284-30-o, yofssh, 200-6, (uint8_t) i, 0, orient&~16); if (j > 0) - minitext(288-30-o, 180, "On", 0, orient); + minitext(288-30-o, 180, GStrings("OPTVAL_ON"), 0, orient); else if ((uint32_t) j != 0x80000000) - minitext(284-30-o, 180, "Off", 2, orient); + minitext(284-30-o, 180, GStrings("OPTVAL_OFF"), 2, orient); if (p->inven_icon >= ICON_SCUBA) - minitext(284-35-o, 180, "Auto", 2, orient); + minitext(284-35-o, 180, GStrings("OPTVAL_AUTO"), 2, orient); minitext_yofs = 0; } @@ -1276,7 +1276,7 @@ void G_DrawStatusBar(int32_t snum) { rotatesprite_fs(sbarx(231-o), sbary(SBY+13), sb16, 0, i, 0, 0, 10+16+permbit); minitext(292-30-o, SBY+24, "%", 6, 10+16+permbit + ROTATESPRITE_MAX); - if (p->inven_icon >= ICON_SCUBA) minitext(284-35-o, SBY+14, "Auto", 2, 10+16+permbit + ROTATESPRITE_MAX); + if (p->inven_icon >= ICON_SCUBA) minitext(284-35-o, SBY+14, GStrings("OPTVAL_AUTO"), 2, 10+16+permbit + ROTATESPRITE_MAX); } } @@ -1286,8 +1286,8 @@ void G_DrawStatusBar(int32_t snum) if (!RR) { - if (j > 0) minitext(288-30-o, SBY+14, "On", 0, 10+16+permbit + ROTATESPRITE_MAX); - else if ((uint32_t) j != 0x80000000) minitext(284-30-o, SBY+14, "Off", 2, 10+16+permbit + ROTATESPRITE_MAX); + if (j > 0) minitext(288-30-o, SBY+14, GStrings("OPTVAL_ON"), 0, 10+16+permbit + ROTATESPRITE_MAX); + else if ((uint32_t) j != 0x80000000) minitext(284-30-o, SBY+14, GStrings("OPTVAL_OFF"), 2, 10+16+permbit + ROTATESPRITE_MAX); } } diff --git a/source/rr/src/screens.cpp b/source/rr/src/screens.cpp index 1cb208e5e..462ac5da2 100644 --- a/source/rr/src/screens.cpp +++ b/source/rr/src/screens.cpp @@ -32,6 +32,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "demo.h" #include "mdsprite.h" #include "gamecvars.h" +#include "menu/menu.h" +#include "mapinfo.h" BEGIN_RR_NS @@ -173,14 +175,14 @@ static void G_ShowScores(void) if (g_mostConcurrentPlayers > 1 && (g_gametypeFlags[ud.coop]&GAMETYPE_SCORESHEET)) { - gametext_center(SCORESHEETOFFSET+58+2, "Multiplayer Totals"); - gametext_center(SCORESHEETOFFSET+58+10, g_mapInfo[G_LastMapInfoIndex()].name); + gametext_center(SCORESHEETOFFSET+58+2, GStrings("Multiplayer Totals")); + gametext_center(SCORESHEETOFFSET+58+10, currentLevel->DisplayName()); t = 0; - minitext(70, SCORESHEETOFFSET+80, "Name", 8, 2+8+16+ROTATESPRITE_MAX); - minitext(170, SCORESHEETOFFSET+80, "Frags", 8, 2+8+16+ROTATESPRITE_MAX); - minitext(200, SCORESHEETOFFSET+80, "Deaths", 8, 2+8+16+ROTATESPRITE_MAX); - minitext(235, SCORESHEETOFFSET+80, "Ping", 8, 2+8+16+ROTATESPRITE_MAX); + minitext(70, SCORESHEETOFFSET+80, GStrings("Name"), 8, 2+8+16+ROTATESPRITE_MAX); + minitext(170, SCORESHEETOFFSET+80, GStrings("Frags"), 8, 2+8+16+ROTATESPRITE_MAX); + minitext(200, SCORESHEETOFFSET+80, GStrings("Deaths"), 8, 2+8+16+ROTATESPRITE_MAX); + minitext(235, SCORESHEETOFFSET+80, GStrings("Ping"), 8, 2+8+16+ROTATESPRITE_MAX); for (i=g_mostConcurrentPlayers-1; i>=0; i--) { @@ -754,7 +756,7 @@ FString GameInterface::statFPS() GameStats GameInterface::getStats() { DukePlayer_t* p = g_player[myconnectindex].ps; - return { p->actors_killed, p->max_actors_killed, p->secret_rooms, p->max_secret_rooms, p->player_par / REALGAMETICSPERSEC }; + return { p->actors_killed, p->max_actors_killed, p->secret_rooms, p->max_secret_rooms, p->player_par / REALGAMETICSPERSEC, p->frag }; } #undef FPS_COLOR @@ -987,14 +989,9 @@ void G_DisplayRest(int32_t smoothratio) if (ud.overhead_on == 2) { const int32_t a = RR ? 0 : ((ud.screen_size > 0) ? 147 : 179); - if (RR && g_lastLevel) - minitext(5, a+6, "CLOSE ENCOUNTERS", 0, 2+8+16+256); - else - { - if (!G_HaveUserMap()) - minitext(5, a+6, g_volumeNames[ud.volume_number], 0, 2+8+16+256); - minitext(5, a+6+6, g_mapInfo[ud.volume_number*MAXLEVELS + ud.level_number].name, 0, 2+8+16+256); - } + if (!G_HaveUserMap()) + minitext(5, a+6, GStrings.localize(gVolumeNames[ud.volume_number]), 0, 2+8+16+256); + minitext(5, a+6+6, currentLevel->DisplayName(), 0, 2+8+16+256); } } } @@ -1014,7 +1011,7 @@ void G_DisplayRest(int32_t smoothratio) G_PrintGameQuotes(screenpeek); - if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1) + if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1 && !M_Active()) { int32_t o = 10|16; @@ -1023,46 +1020,7 @@ void G_DisplayRest(int32_t smoothratio) else if (g_levelTextTime < 5) o |= 1; - if (g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name != NULL) - { - char const * const fn = currentboardfilename[0] != 0 && - ud.volume_number == 0 && ud.level_number == 7 - ? currentboardfilename - : g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name; - - menutext_(160<<16, (90+16+8)<<16, -g_levelTextTime+22/*quotepulseshade*/, fn, o, TEXT_XCENTER); - } - } - - if (I_EscapeTrigger() && ud.overhead_on == 0 - && ud.show_help == 0 - && g_player[myconnectindex].ps->newowner == -1) - { - if ((g_player[myconnectindex].ps->gm&MODE_MENU) == MODE_MENU && g_currentMenu <= MENU_MAIN_INGAME) - { - I_EscapeTriggerClear(); - S_PlaySound(EXITMENUSOUND); - Menu_Change(MENU_CLOSE); - if (!ud.pause_on) - S_PauseSounds(false); - } - else if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU && - g_player[myconnectindex].ps->newowner == -1 && - (g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE) - { - I_EscapeTriggerClear(); - S_PauseSounds(true); - - Menu_Open(myconnectindex); - - if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) ready2send = 0; - - if (g_player[myconnectindex].ps->gm&MODE_GAME) Menu_Change(MENU_MAIN_INGAME); - else Menu_Change(MENU_MAIN); - screenpeek = myconnectindex; - - S_MenuSound(); - } + menutext_(160<<16, (90+16+8)<<16, -g_levelTextTime+22/*quotepulseshade*/, currentLevel->DisplayName(), o, TEXT_XCENTER); } if (g_player[myconnectindex].ps->newowner == -1 && ud.overhead_on == 0 && cl_crosshair && ud.camerasprite == -1) @@ -1083,7 +1041,7 @@ void G_DisplayRest(int32_t smoothratio) if (ud.pause_on==1 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0) - menutext_center(100, "Game Paused"); + menutext_center(100, GStrings("Game Paused")); if (cl_showcoords) G_PrintCoords(screenpeek); @@ -1148,7 +1106,7 @@ void G_DisplayRest(int32_t smoothratio) { Bsprintf(tempbuf, "%s^00 has called a vote for map", g_player[voting].user_name); gametext_center(40, tempbuf); - Bsprintf(tempbuf, "%s (E%dL%d)", g_mapInfo[vote_episode*MAXLEVELS + vote_map].name, vote_episode+1, vote_map+1); + Bsprintf(tempbuf, "%s (E%dL%d)", mapList[vote_episode*MAXLEVELS + vote_map].DisplayName(), vote_episode+1, vote_map+1); gametext_center(48, tempbuf); gametext_center(70, "Press F1 to Accept, F2 to Decline"); } @@ -1170,8 +1128,8 @@ void G_DisplayRest(int32_t smoothratio) { if (g_player[myconnectindex].ps->gm&MODE_TYPE) Net_SendMessage(); - else - M_DisplayMenus(); + //else + //M_DisplayMenus(); } { @@ -1266,7 +1224,7 @@ int inExtraScreens = 0; void G_DisplayExtraScreens(void) { - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); if (RR) return; @@ -1340,7 +1298,7 @@ void G_DisplayLogo(void) renderFlushPerms(); videoNextPage(); - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); // JBF 20031228 S_ClearSoundLocks(); // JBF 20031228 if (RRRA) @@ -1423,7 +1381,7 @@ void G_DisplayLogo(void) { Net_GetPackets(); - if (testkopen("3dr.ivf", 0) || testkopen("3dr.anm", 0)) + if (fileSystem.FileExists("3dr.ivf") || fileSystem.FileExists("3dr.anm")) { Anim_Play("3dr.anm"); G_FadePalette(0, 0, 0, 252); @@ -1754,7 +1712,7 @@ static void G_BonusCutscenes(void) G_HandleEventsWhileNoInput(); fadepal(0, 0, 0, 0, 252, 4); - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); S_ClearSoundLocks(); break; @@ -1762,7 +1720,7 @@ static void G_BonusCutscenes(void) case 1: videoSetViewableArea(0, 0, xdim-1, ydim-1); - S_StopMusic(); + Mus_Stop(); videoClearScreen(0L); videoNextPage(); @@ -1790,7 +1748,7 @@ static void G_BonusCutscenes(void) case 3: videoSetViewableArea(0, 0, xdim-1, ydim-1); - S_StopMusic(); + Mus_Stop(); videoClearScreen(0L); videoNextPage(); @@ -1826,11 +1784,11 @@ static void G_BonusCutscenes(void) P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1); // JBF 20040308 // G_FadePalette(0,0,0,252); videoClearScreen(0L); - menutext_center(60, "Thanks to all our"); - menutext_center(60+16, "fans for giving"); - menutext_center(60+16+16, "us big heads."); - menutext_center(70+16+16+16, "Look for a Duke Nukem 3D"); - menutext_center(70+16+16+16+16, "sequel soon."); + menutext_center(60, GStrings("Thanks to all our")); + menutext_center(60+16, GStrings("fans for giving")); + menutext_center(60+16+16, GStrings("us big heads.")); + menutext_center(70+16+16+16, GStrings("Look for a Duke Nukem 3D")); + menutext_center(70+16+16+16+16, GStrings("sequel soon.")); videoNextPage(); fadepal(0, 0, 0, 252, 0, -12); @@ -1858,7 +1816,7 @@ static void G_BonusCutscenes(void) break; case 2: - S_StopMusic(); + Mus_Stop(); videoClearScreen(0L); videoNextPage(); if (adult_lockout == 0) @@ -1940,13 +1898,13 @@ static void G_DisplayMPResultsScreen(void) rotatesprite_fs(160<<16, 34<<16, RR ? 23592L : 65536L, 0, INGAMEDUKETHREEDEE, 0, 0, 10); if (!RR && PLUTOPAK) // JBF 20030804 rotatesprite_fs((260)<<16, 36<<16, 65536L, 0, PLUTOPAKSPRITE+2, 0, 0, 2+8); - gametext_center(58+(RR ? 0 : 2), "Multiplayer Totals"); - gametext_center(58+10, g_mapInfo[G_LastMapInfoIndex()].name); + gametext_center(58+(RR ? 0 : 2), GStrings("Multiplayer Totals")); + gametext_center(58+10, currentLevel->DisplayName()); - gametext_center_shade(RR ? 175 : 165, "Press any key or button to continue", quotepulseshade); + gametext_center_shade(RR ? 175 : 165, GStrings("Presskey"), quotepulseshade); - minitext(38, 80, "Name", 8, 2+8+16+128); - minitext(269, 80, "Kills", 8, 2+8+16+128); + minitext(38, 80, GStrings("Name"), 8, 2+8+16+128); + minitext(269, 80, GStrings("Kills"), 8, 2+8+16+128); for (i=0; i9; ii/=10, ij++) { } + for (ii=currentLevel->parTime/(60), ij=1; ii>9; ii/=10, ij++) { } clockpad = max(clockpad, ij); - if (g_mapInfo[G_LastMapInfoIndex()].designertime) + if (currentLevel->designerTime) { - for (ii=g_mapInfo[G_LastMapInfoIndex()].designertime/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { } + for (ii=currentLevel->designerTime/(60), ij=1; ii>9; ii/=10, ij++) { } clockpad = max(clockpad, ij); } } @@ -2042,13 +2000,13 @@ const char* G_PrintParTime(void) { if (ud.last_level < 1) return ""; - return G_PrintTime2(g_mapInfo[G_LastMapInfoIndex()].partime); + return G_PrintTime2(currentLevel->parTime * REALGAMETICSPERSEC); } const char* G_PrintDesignerTime(void) { if (ud.last_level < 1) return ""; - return G_PrintTime2(g_mapInfo[G_LastMapInfoIndex()].designertime); + return G_PrintTime2(currentLevel->designerTime*REALGAMETICSPERSEC); } const char* G_PrintBestTime(void) { @@ -2073,20 +2031,9 @@ void G_BonusScreen(int32_t bonusonly) } else { - lastmapname = g_mapInfo[G_LastMapInfoIndex()].name; - if (!lastmapname) // this isn't right but it's better than no name at all - lastmapname = g_mapInfo[G_LastMapInfoIndex()].name; + lastmapname = currentLevel->DisplayName(); } - if (RR) - { - if ((g_lastLevel && ud.volume_number == 2) || g_vixenLevel) - lastmapname = "CLOSE ENCOUNTERS"; - else if (g_turdLevel) - lastmapname = "SMELTING PLANT"; - } - - fadepal(0, 0, 0, 0, 252, RR ? 4 : 28); videoSetViewableArea(0, 0, xdim-1, ydim-1); videoClearScreen(0L); @@ -2107,7 +2054,7 @@ void G_BonusScreen(int32_t bonusonly) totalclock = 0; bonuscnt = 0; - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); S_ClearSoundLocks(); @@ -2156,9 +2103,9 @@ void G_BonusScreen(int32_t bonusonly) if (lastmapname) menutext_center(20-6, lastmapname); - menutext_center(36-6, "Completed"); + menutext_center(36-6, GStrings("Completed")); - gametext_center_shade(192, "Press any key or button to continue", quotepulseshade); + gametext_center_shade(192, GStrings("PRESSKEY"), quotepulseshade); if (MusicEnabled()) S_PlaySound(BONUSMUSIC); @@ -2178,7 +2125,7 @@ void G_BonusScreen(int32_t bonusonly) if (lastmapname) menutext(80,16, lastmapname); - menutext(15, 192, "Press any key to continue"); + menutext(15, 192, GStrings("PRESSKEY")); } videoNextPage(); @@ -2261,16 +2208,16 @@ void G_BonusScreen(int32_t bonusonly) { if (lastmapname) menutext_center(20-6, lastmapname); - menutext_center(36-6, "Completed"); + menutext_center(36-6, GStrings("Completed")); - gametext_center_shade(192, "Press any key or button to continue", quotepulseshade); + gametext_center_shade(192, GStrings("PRESSKEY"), quotepulseshade); } else { if (lastmapname) menutext(80, 16, lastmapname); - menutext(15, 192, "Press any key to continue"); + menutext(15, 192, GStrings("PRESSKEY")); } const int yystep = RR ? 16 : 10; @@ -2279,28 +2226,28 @@ void G_BonusScreen(int32_t bonusonly) yy = zz = RR ? 48 : 59; if (!RR) - gametext(10, yy+9, "Your Time:"); + gametext(10, yy+9, GStrings("TXT_YourTime")); else - menutext(30, yy, "Yer Time:"); + menutext(30, yy, GStrings("TXT_YerTime")); yy+= yystep; if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0])) { - if (g_mapInfo[G_LastMapInfoIndex()].partime) + if (currentLevel->parTime) { if (!RR) - gametext(10, yy+9, "Par Time:"); + gametext(10, yy+9, GStrings("TXT_ParTime")); else - menutext(30, yy, "Par Time:"); + menutext(30, yy, GStrings("TXT_ParTime")); yy+=yystep; } - if (g_mapInfo[G_LastMapInfoIndex()].designertime) + if (currentLevel->designerTime) { // EDuke 2.0 / NAM source suggests "Green Beret's Time:" if (DUKE) - gametext(10, yy+9, "3D Realms' Time:"); + gametext(10, yy+9, GStrings("TXT_3DRTIME")); else if (RR) - menutext(30, yy, "Xatrix Time:"); + menutext(30, yy, GStrings("TXT_XTRTIME")); yy+=yystep; } @@ -2333,7 +2280,7 @@ void G_BonusScreen(int32_t bonusonly) { gametext_number((320>>2)+71, yy+9, tempbuf); if (g_player[myconnectindex].ps->player_par < ud.playerbest) - gametext((320>>2)+89+(clockpad*24), yy+9, "New record!"); + gametext((320>>2)+89+(clockpad*24), yy+9, GStrings("TXT_NEWRECORD")); } else { @@ -2343,14 +2290,14 @@ void G_BonusScreen(int32_t bonusonly) } } else if (!RR) - gametext_pal((320>>2)+71, yy+9, "Cheated!", 2); + gametext_pal((320>>2)+71, yy+9, GStrings("TXT_Cheated"), 2); else - menutext(191, yy, "Cheated!"); + menutext(191, yy, GStrings("TXT_Cheated")); yy+=yystep; if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0])) { - if (g_mapInfo[G_LastMapInfoIndex()].partime) + if (currentLevel->parTime) { G_PrintParTime(); if (!RR) @@ -2359,7 +2306,7 @@ void G_BonusScreen(int32_t bonusonly) menutext(191, yy, tempbuf); yy+=yystep; } - if (g_mapInfo[G_LastMapInfoIndex()].designertime) + if (currentLevel->designerTime) { G_PrintDesignerTime(); if (DUKE) @@ -2386,14 +2333,14 @@ void G_BonusScreen(int32_t bonusonly) if (totalclock > (60*6)) { if (!RR) - gametext(10, yy+9, "Enemies Killed:"); + gametext(10, yy+9, GStrings("TXT_EnemiesKilled")); else - menutext(30, yy, "Varmints Killed:"); + menutext(30, yy, GStrings("TXT_VarmintsKilled")); yy += yystep; if (!RR) - gametext(10, yy+9, "Enemies Left:"); + gametext(10, yy+9, GStrings("TXT_EnemiesLeft")); else - menutext(30, yy, "Varmints Left:"); + menutext(30, yy, GStrings("TXT_VarmintsLeft")); yy += yystep; if (bonuscnt == 2) @@ -2421,9 +2368,9 @@ void G_BonusScreen(int32_t bonusonly) if (ud.player_skill > 3 && !RR) { if (!RR) - gametext((320>>2)+70, yy+9, "N/A"); + gametext((320>>2)+70, yy+9, GStrings("TXT_N_A")); else - menutext(231,yy, "N/A"); + menutext(231,yy, GStrings("TXT_N_A")); yy += yystep; } else @@ -2444,14 +2391,14 @@ void G_BonusScreen(int32_t bonusonly) if (totalclock > (60*9)) { if (!RR) - gametext(10, yy+9, "Secrets Found:"); + gametext(10, yy+9, GStrings("TXT_SECFND")); else - menutext(30, yy, "Secrets Found:"); + menutext(30, yy, GStrings("TXT_SECFND")); yy += yystep; if (!RR) - gametext(10, yy+9, "Secrets Missed:"); + gametext(10, yy+9, GStrings("TXT_SECMISS")); else - menutext(30, yy, "Secrets Missed:"); + menutext(30, yy, GStrings("TXT_SECMISS")); yy += yystep; if (bonuscnt == 4) bonuscnt++; @@ -2653,17 +2600,9 @@ void G_BonusScreenRRRA(int32_t bonusonly) } else { - lastmapname = g_mapInfo[G_LastMapInfoIndex()].name; - if (!lastmapname) // this isn't right but it's better than no name at all - lastmapname = g_mapInfo[G_LastMapInfoIndex()].name; + lastmapname = currentLevel->DisplayName(); } - if ((g_lastLevel && ud.volume_number == 2) || g_vixenLevel) - lastmapname = "CLOSE ENCOUNTERS"; - else if (g_turdLevel) - lastmapname = "SMELTIN' PLANT"; - - fadepal(0, 0, 0, 0, 252, 4); videoSetViewableArea(0, 0, xdim-1, ydim-1); videoClearScreen(0L); @@ -2699,7 +2638,7 @@ void G_BonusScreenRRRA(int32_t bonusonly) totalclock = 0; bonuscnt = 0; - S_StopMusic(); + Mus_Stop(); FX_StopAllSounds(); S_ClearSoundLocks(); @@ -2844,7 +2783,7 @@ void G_BonusScreenRRRA(int32_t bonusonly) if (lastmapname) menutext(80, 16, lastmapname); - menutext(15, 192, "Press any key to continue"); + menutext(15, 192, GStrings("TXT_PRESSKEY")); const int yystep = 16; if (totalclock > (60*3)) @@ -2856,14 +2795,14 @@ void G_BonusScreenRRRA(int32_t bonusonly) yy+= yystep; if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0])) { - if (g_mapInfo[G_LastMapInfoIndex()].partime) + if (currentLevel->parTime) { - menutext(30, yy, "Par Time:"); + menutext(30, yy, GStrings("TXT_PARTIME")); yy+=yystep; } - if (g_mapInfo[G_LastMapInfoIndex()].designertime) + if (currentLevel->designerTime) { - menutext(30, yy, "Xatrix Time:"); + menutext(30, yy, GStrings("TXT_XTRTIME")); yy+=yystep; } @@ -2899,13 +2838,13 @@ void G_BonusScreenRRRA(int32_t bonusonly) if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0])) { - if (g_mapInfo[G_LastMapInfoIndex()].partime) + if (currentLevel->parTime) { G_PrintParTime(); menutext(191, yy, tempbuf); yy+=yystep; } - if (g_mapInfo[G_LastMapInfoIndex()].designertime) + if (currentLevel->designerTime) { G_PrintDesignerTime(); menutext(191, yy, tempbuf); @@ -2925,9 +2864,9 @@ void G_BonusScreenRRRA(int32_t bonusonly) zz = yy += 16; if (totalclock > (60*6)) { - menutext(30, yy, "Varmints Killed:"); + menutext(30, yy, GStrings("TXT_VARMINTSKILLED")); yy += yystep; - menutext(30, yy, "Varmints Left:"); + menutext(30, yy, GStrings("TXT_VARMINTSLEFT")); yy += yystep; if (bonuscnt == 2) @@ -2964,9 +2903,9 @@ void G_BonusScreenRRRA(int32_t bonusonly) zz = yy += 0; if (totalclock > (60*9)) { - menutext(30, yy, "Secrets Found:"); + menutext(30, yy, GStrings("TXT_SECFND")); yy += yystep; - menutext(30, yy, "Secrets Missed:"); + menutext(30, yy, GStrings("TXT_SECMISS")); yy += yystep; if (bonuscnt == 4) bonuscnt++; diff --git a/source/rr/src/screens.h b/source/rr/src/screens.h index cf9018678..d6abe2bcd 100644 --- a/source/rr/src/screens.h +++ b/source/rr/src/screens.h @@ -26,12 +26,6 @@ extern void G_DisplayExtraScreens(void); extern void G_DisplayLogo(void); extern void G_DoOrderScreen(void); -static inline int G_LastMapInfoIndex(void) -{ - Bassert(ud.last_level >= 1); // NOTE: last_level is 1-based - return ud.volume_number*MAXLEVELS + ud.last_level-1; -} - #ifdef DEBUGGINGAIDS typedef struct { uint32_t lastgtic; diff --git a/source/rr/src/screentext.cpp b/source/rr/src/screentext.cpp index a16907825..6aea65a7b 100644 --- a/source/rr/src/screentext.cpp +++ b/source/rr/src/screentext.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "sbar.h" #include "menus.h" +#include "gstrings.h" BEGIN_RR_NS @@ -467,7 +468,7 @@ vec2_t G_ScreenText(const int32_t font, int32_t xspace, int32_t yline, int32_t xbetween, int32_t ybetween, const int32_t f, const int32_t x1, const int32_t y1, const int32_t x2, const int32_t y2) { - vec2_t size = { 0, 0, }; // eventually the return value + vec2_t size = { 0, 0, }; // eventually the return value vec2_t origin = { 0, 0, }; // where to start, depending on the alignment vec2_t pos = { 0, 0, }; // holds the coordinate position as we draw each character tile of the string vec2_t extent = { 0, 0, }; // holds the x-width of each character and the greatest y-height of each line @@ -985,20 +986,24 @@ void captionmenutext(int32_t x, int32_t y, char const *t) int32_t user_quote_time[MAXUSERQUOTES]; static char user_quote[MAXUSERQUOTES][178]; -void G_AddUserQuote(const char *daquote) +void G_AddUserQuote(const char* daquote) { - int32_t i; + int32_t i; - for (i=MAXUSERQUOTES-1; i>0; i--) - { - Bstrcpy(user_quote[i], user_quote[i-1]); - user_quote_time[i] = user_quote_time[i-1]; - } - Bstrcpy(user_quote[0], daquote); - OSD_Printf("%s\n", daquote); + if (hud_messages == 0) return; + Printf(PRINT_MEDIUM | PRINT_NOTIFY, "%s\n", daquote); + if (hud_messages == 1) + { + for (i = MAXUSERQUOTES - 1; i > 0; i--) + { + Bstrcpy(user_quote[i], user_quote[i - 1]); + user_quote_time[i] = user_quote_time[i - 1]; + } + Bstrcpy(user_quote[0], daquote); - user_quote_time[0] = hud_messagetime; - pub = NUMPAGES; + user_quote_time[0] = hud_messagetime; + pub = NUMPAGES; + } } int32_t textsc(int32_t sc) @@ -1050,6 +1055,8 @@ static FORCE_INLINE int32_t text_ypos(void) #endif } +static FString text_quote; // To put text into the quote display that does not come from the quote array. (Is it really necessary to implement everything as a hack??? :( ) + // this handles both multiplayer and item pickup message type text // both are passed on to gametext void G_PrintGameQuotes(int32_t snum) @@ -1070,12 +1077,6 @@ void G_PrintGameQuotes(int32_t snum) if (k <= 1) break; - if (EDUKE32_PREDICT_FALSE(apStrings[ps->ftq] == NULL)) - { - OSD_Printf(OSD_ERROR "%s %d null quote %d\n", __FILE__, __LINE__, ps->ftq); - break; - } - int32_t y = ybase; if (reserved_quote) { @@ -1105,8 +1106,9 @@ void G_PrintGameQuotes(int32_t snum) } #endif - height = gametext_(x, y, apStrings[ps->ftq], textsh(k), pal, texto(k), texta(k), TEXT_XCENTER).y + (1<<16); - } + if (text_quote.IsNotEmpty() && ps->ftq == -32768) height = gametext_(x, y, text_quote, textsh(k), pal, texto(k), texta(k), TEXT_XCENTER).y + (1 << 16); + else height = gametext_(x, y, quoteMgr.GetQuote(ps->ftq), textsh(k), pal, texto(k), texta(k), TEXT_XCENTER).y + (1 << 16); + } while (0); @@ -1144,26 +1146,48 @@ void P_DoQuote(int32_t q, DukePlayer_t *p) q &= ~MAXQUOTES; } - if (EDUKE32_PREDICT_FALSE(apStrings[q] == NULL)) - { - OSD_Printf(OSD_ERROR "%s %d null quote %d\n", __FILE__, __LINE__, q); - return; - } - if (p->fta > 0 && q != QUOTE_RESERVED && q != QUOTE_RESERVED2) if (p->ftq == QUOTE_RESERVED || p->ftq == QUOTE_RESERVED2) return; - p->fta = 100; - if (p->ftq != q) { - if (p == g_player[screenpeek].ps && apStrings[q][0] != '\0') - OSD_Printf(cq ? OSDTEXT_DEFAULT "%s\n" : "%s\n", apStrings[q]); + auto qu = quoteMgr.GetQuote(q); + if (p == g_player[screenpeek].ps && qu[0] != '\0') + Printf((cq ? PRINT_LOW : PRINT_MEDIUM) | PRINT_NOTIFY, "%s\n", qu); - p->ftq = q; } - pub = NUMPAGES; - pus = NUMPAGES; + if (hud_messages == 1) + { + p->ftq = q; + p->fta = 100; + pub = NUMPAGES; + pus = NUMPAGES; + } } + +void GameInterface::DoPrintMessage(int prio, const char* t) +{ + auto p = g_player[myconnectindex].ps; // text quotes always belong to the local player. + int32_t cq = 0; + + if (hud_messages == 0 || !(p->gm & MODE_GAME)) + return; + + if (p->fta > 0) + if (p->ftq == QUOTE_RESERVED || p->ftq == QUOTE_RESERVED2) return; + + if (p == g_player[screenpeek].ps) + Printf(prio|PRINT_NOTIFY, cq ? OSDTEXT_DEFAULT "%s\n" : "%s\n", t); + + if (hud_messages == 1) + { + p->fta = 100; + p->ftq = -32768; + text_quote = t; + pub = NUMPAGES; + pus = NUMPAGES; + } +} + END_RR_NS diff --git a/source/rr/src/sector.cpp b/source/rr/src/sector.cpp index b716b3142..a75f5f9e6 100644 --- a/source/rr/src/sector.cpp +++ b/source/rr/src/sector.cpp @@ -3649,12 +3649,12 @@ void P_HandleSharedKeys(int playerNum) else ud.pause_on = 1+SHIFTS_IS_PRESSED; if (ud.pause_on) { - S_PauseMusic(true); + Mus_SetPaused(true); S_PauseSounds(true); } else { - if (MusicEnabled()) S_PauseMusic(false); + Mus_SetPaused(false); S_PauseSounds(false); diff --git a/source/rr/src/sector.h b/source/rr/src/sector.h index 8647cae3f..f167be4a2 100644 --- a/source/rr/src/sector.h +++ b/source/rr/src/sector.h @@ -98,12 +98,9 @@ typedef struct { } mapstate_t; typedef struct { - int32_t partime, designertime; - char *name, *filename, *musicfn; mapstate_t *savedstate; } map_t; -//extern map_t g_mapInfo[(MAXVOLUMES+1)*MAXLEVELS]; // +1 volume for "intro", "briefing" music void G_ActivateBySector(int sect,int spriteNum); int S_FindMusicSFX(int sectNum, int *sndptr); diff --git a/source/rr/src/sounds.cpp b/source/rr/src/sounds.cpp index 85cf2b899..b86632a8f 100644 --- a/source/rr/src/sounds.cpp +++ b/source/rr/src/sounds.cpp @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "openaudio.h" #include "z_music.h" #include +#include "mapinfo.h" BEGIN_RR_NS @@ -77,7 +78,6 @@ void S_SoundStartup(void) S_PrecacheSounds(); snd_fxvolume.Callback(); - S_MusicVolume(mus_volume); snd_reversestereo.Callback(); FX_SetCallBack(S_Callback); @@ -86,9 +86,6 @@ void S_SoundStartup(void) void S_SoundShutdown(void) { - if (MusicVoice >= 0) - S_MusicShutdown(); - if (FX_Shutdown() != FX_Ok) { Bsprintf(tempbuf, "S_SoundShutdown(): error: %s", FX_ErrorString(FX_Error)); @@ -96,26 +93,7 @@ void S_SoundShutdown(void) } } -void S_MusicStartup(void) -{ - initprintf("Initializing music...\n"); - if (MUSIC_Init(MusicDevice) == MUSIC_Ok) - { - MUSIC_SetVolume(mus_volume); - return; - } - - initprintf("S_MusicStartup(): failed initializing\n"); -} - -void S_MusicShutdown(void) -{ - S_StopMusic(); - - if (MUSIC_Shutdown() != MUSIC_Ok) - initprintf("%s\n", MUSIC_ErrorString(MUSIC_ErrorCode)); -} void S_PauseSounds(bool paused) { if (SoundPaused == paused) @@ -131,28 +109,6 @@ void S_PauseSounds(bool paused) } } - - -void S_MusicVolume(int32_t volume) -{ - if (MusicIsWaveform && MusicVoice >= 0) - FX_SetPan(MusicVoice, volume, volume, volume); - - MUSIC_SetVolume(volume); -} - -void S_RestartMusic(void) -{ - if (ud.recstat != 2 && g_player[myconnectindex].ps->gm&MODE_GAME) - { - S_PlayLevelMusicOrNothing(g_musicIndex); - } - else - { - S_PlaySpecialMusicOrNothing(MUS_INTRO); - } -} - void S_MenuSound(void) { static int SoundNum; @@ -166,185 +122,21 @@ void S_MenuSound(void) S_PlaySound(s); } -#if 0 // In case you desperately want the old system back... ;) -static int S_PlayMusic(const char *, const char *fn, int loop) -{ - if (!MusicEnabled()) - return 0; - - if (fn == NULL) - return 1; - - auto fp = S_OpenAudio(fn, 0, 1); - if (!fp.isOpen()) - { - OSD_Printf(OSD_ERROR "S_PlayMusic(): error: can't open \"%s\" for playback!\n",fn); - return 2; - } - - int32_t MusicLen = fp.GetLength(); - - if (EDUKE32_PREDICT_FALSE(MusicLen < 4)) - { - OSD_Printf(OSD_ERROR "S_PlayMusic(): error: empty music file \"%s\"\n", fn); - return 3; - } - - char * MyMusicPtr = (char *)Xaligned_alloc(16, MusicLen); - int MyMusicSize = fp.Read(MyMusicPtr, MusicLen); - - if (EDUKE32_PREDICT_FALSE(MyMusicSize != MusicLen)) - { - OSD_Printf(OSD_ERROR "S_PlayMusic(): error: read %d bytes from \"%s\", expected %d\n", - MyMusicSize, fn, MusicLen); - ALIGNED_FREE_AND_NULL(MyMusicPtr); - return 4; - } - - if (!Bmemcmp(MyMusicPtr, "MThd", 4)) - { - int32_t retval = MUSIC_PlaySong(MyMusicPtr, MyMusicSize, loop); - - if (retval != MUSIC_Ok) - { - ALIGNED_FREE_AND_NULL(MyMusicPtr); - return 5; - } - - if (MusicIsWaveform && MusicVoice >= 0) - { - FX_StopSound(MusicVoice); - MusicVoice = -1; - } - - MusicIsWaveform = 0; - ALIGNED_FREE_AND_NULL(MusicPtr); - MusicPtr = MyMusicPtr; - g_musicSize = MyMusicSize; - } - else - { - int MyMusicVoice = FX_Play(MyMusicPtr, MusicLen, 0, 0, 0, mus_volume, mus_volume, mus_volume, - FX_MUSIC_PRIORITY, 1.f, MUSIC_ID); - - if (MyMusicVoice <= FX_Ok) - { - ALIGNED_FREE_AND_NULL(MyMusicPtr); - return 5; - } - - if (MusicIsWaveform && MusicVoice >= 0) - FX_StopSound(MusicVoice); - - MUSIC_StopSong(); - - MusicVoice = MyMusicVoice; - MusicIsWaveform = 1; - ALIGNED_FREE_AND_NULL(MusicPtr); - MusicPtr = MyMusicPtr; - g_musicSize = MyMusicSize; - } - - return 0; -} - - -void S_StopMusic(void) -{ - MusicPaused = 0; - - if (MusicIsWaveform && MusicVoice >= 0) - { - FX_StopSound(MusicVoice); - MusicVoice = -1; - MusicIsWaveform = 0; - } - - MUSIC_StopSong(); - - ALIGNED_FREE_AND_NULL(MusicPtr); - g_musicSize = 0; -} - -void S_PauseMusic(bool paused) -{ - if (MusicPaused == paused || (MusicIsWaveform && MusicVoice < 0)) - return; - - MusicPaused = paused; - - if (MusicIsWaveform) - { - FX_PauseVoice(MusicVoice, paused); - return; - } - - if (paused) - MUSIC_Pause(); - else - MUSIC_Continue(); -} - - - -#else -static int S_PlayMusic(const char *mapname, const char* fn, bool looping = true) -{ - return Mus_Play(mapname, fn, looping); -} - -void S_StopMusic(void) -{ - Mus_Stop(); -} - - -void S_PauseMusic(bool paused) -{ - Mus_SetPaused(paused); -} - -#endif - - -static void S_SetMusicIndex(unsigned int m) -{ - g_musicIndex = m; - ud.music_episode = m / MAXLEVELS; - ud.music_level = m % MAXLEVELS; -} - -bool S_TryPlayLevelMusic(unsigned int m) -{ - // For RR only explicitly invalidate the music name, but still allow the music code to run its own music substitution logic based on map names. - if (!S_PlayMusic(g_mapInfo[m].filename,RR? nullptr : g_mapInfo[m].musicfn)) - { - S_SetMusicIndex(m); - return false; - } - - return true; -} void S_PlayLevelMusicOrNothing(unsigned int m) { - if (S_TryPlayLevelMusic(m)) - { - //S_StopMusic(); - S_SetMusicIndex(m); - } + Mus_Play(mapList[m].labelName, RR ? nullptr : mapList[m].music, true); } int S_TryPlaySpecialMusic(unsigned int m) { if (RR) return 1; - char const * musicfn = g_mapInfo[m].musicfn; - if (musicfn != NULL) + auto &musicfn = mapList[m].music; + if (musicfn.IsNotEmpty()) { - if (!S_PlayMusic(nullptr, musicfn, 1)) + if (!Mus_Play(nullptr, musicfn, 1)) { - S_SetMusicIndex(m); return 0; } } @@ -355,24 +147,20 @@ int S_TryPlaySpecialMusic(unsigned int m) void S_PlayRRMusic(int newTrack) { char fileName[16]; - if (!RR) + if (!RR || !mus_redbook) return; - S_StopMusic(); + Mus_Stop(); g_cdTrack = newTrack != -1 ? newTrack : g_cdTrack+1; if (newTrack != 10 && (g_cdTrack > 9 || g_cdTrack < 2)) g_cdTrack = 2; Bsprintf(fileName, "track%.2d.ogg", g_cdTrack); - S_PlayMusic(fileName, 0); + Mus_Play(fileName, 0, true); } void S_PlaySpecialMusicOrNothing(unsigned int m) { - if (S_TryPlaySpecialMusic(m)) - { - //S_StopMusic(); - S_SetMusicIndex(m); - } + S_TryPlaySpecialMusic(m); } void S_Cleanup(void) @@ -394,7 +182,6 @@ void S_Cleanup(void) // for which there was no open slot to keep track of the voice if (num >= (MAXSOUNDS*MAXSOUNDINSTANCES)) { - --g_soundlocks[num-(MAXSOUNDS*MAXSOUNDINSTANCES)]; continue; } @@ -422,8 +209,6 @@ void S_Cleanup(void) voice.id = 0; voice.dist = UINT16_MAX; voice.clock = 0; - - --g_soundlocks[num]; } } @@ -444,9 +229,8 @@ int32_t S_LoadSound(int num) } int32_t l = fp.GetLength(); - g_soundlocks[num] = 200; snd.siz = l; - cacheAllocateBlock((intptr_t *)&snd.ptr, l, &g_soundlocks[num]); + cacheAllocateBlock((intptr_t *)&snd.ptr, l, nullptr); l = fp.Read(snd.ptr, l); return l; @@ -698,14 +482,11 @@ int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) if (snd.num > 0 && PN(spriteNum) != MUSICANDSFX) S_StopEnvSound(sndNum, spriteNum); - if (++g_soundlocks[sndNum] < 200) - g_soundlocks[sndNum] = 200; int const sndSlot = S_GetSlot(sndNum); if (sndSlot >= MAXSOUNDINSTANCES) { - g_soundlocks[sndNum]--; return -1; } @@ -713,7 +494,6 @@ int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) if (repeatp && (snd.m & SF_ONEINST_INTERNAL) && snd.num > 0) { - g_soundlocks[sndNum]--; return -1; } @@ -727,7 +507,6 @@ int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) if (voice <= FX_Ok) { - g_soundlocks[sndNum]--; return -1; } @@ -760,14 +539,10 @@ int S_PlaySound(int num) int const pitch = S_GetPitch(num); - if (++g_soundlocks[num] < 200) - g_soundlocks[num] = 200; - sndnum = S_GetSlot(num); if (sndnum >= MAXSOUNDINSTANCES) { - g_soundlocks[num]--; return -1; } @@ -778,7 +553,6 @@ int S_PlaySound(int num) if (voice <= FX_Ok) { - g_soundlocks[num]--; return -1; } @@ -920,17 +694,6 @@ void S_Callback(intptr_t num) dnum++; } -void S_ClearSoundLocks(void) -{ -#ifdef CACHING_DOESNT_SUCK - int32_t i; - int32_t const msp = g_highestSoundIdx; - - for (native_t i = 0; i <= msp; ++i) - if (g_soundlocks[i] >= 200) - g_soundlocks[i] = 199; -#endif -} bool A_CheckSoundPlaying(int spriteNum, int soundNum) { @@ -963,8 +726,8 @@ bool A_CheckAnySoundPlaying(int spriteNum) bool S_CheckSoundPlaying(int spriteNum, int soundNum) { - if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return 0; - return (spriteNum == -1) ? (g_soundlocks[soundNum] > 200) : (g_sounds[soundNum].num != 0); + if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return false; + return (g_sounds[soundNum].num != 0); } END_RR_NS diff --git a/source/rr/src/sounds.h b/source/rr/src/sounds.h index 7b7c80785..39cb58900 100644 --- a/source/rr/src/sounds.h +++ b/source/rr/src/sounds.h @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define sounds_public_h_ #include "sounds_common.h" +#include "z_music.h" BEGIN_RR_NS @@ -57,7 +58,6 @@ typedef struct char pr, m; // 2b } sound_t; -extern uint8_t g_soundlocks[MAXSOUNDS]; extern sound_t g_sounds[MAXSOUNDS]; extern int32_t g_skillSoundVoice; extern int32_t g_numEnvSoundsPlaying,g_highestSoundIdx; @@ -68,18 +68,12 @@ void S_Callback(intptr_t num); bool A_CheckAnySoundPlaying(int spriteNum); bool S_CheckSoundPlaying(int spriteNum,int soundNum); void S_Cleanup(void); -void S_ClearSoundLocks(void); +inline void S_ClearSoundLocks(void) {} int32_t S_LoadSound(uint32_t num); void S_PrecacheSounds(void); void S_MenuSound(void); -void S_MusicShutdown(void); -void S_MusicStartup(void); -void S_MusicVolume(int32_t volume); -void S_RestartMusic(void); -void S_PauseMusic(bool paused); void S_PauseSounds(bool paused); void S_PlayRRMusic(int newTrack = -1); -bool S_TryPlayLevelMusic(unsigned int m); void S_PlayLevelMusicOrNothing(unsigned int); int S_TryPlaySpecialMusic(unsigned int); void S_PlaySpecialMusicOrNothing(unsigned int); @@ -89,7 +83,6 @@ void S_SoundShutdown(void); void S_SoundStartup(void); void S_StopEnvSound(int32_t num,int32_t i); void S_StopAllSounds(void); -void S_StopMusic(void); void S_Update(void); void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset); diff --git a/source/sw/CMakeLists.txt b/source/sw/CMakeLists.txt index 197582dcd..6de3ea9b1 100644 --- a/source/sw/CMakeLists.txt +++ b/source/sw/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../common/textures ${CMAKE_CURRENT_SOURCE_DIR}/../common/fonts ${CMAKE_CURRENT_SOURCE_DIR}/../common/2d + ${CMAKE_CURRENT_SOURCE_DIR}/../common/music ${CMAKE_CURRENT_SOURCE_DIR}/../platform ) @@ -102,6 +103,7 @@ set( PCH_SOURCES src/zilla.cpp src/zombie.cpp src/swcvar.cpp + src/d_menu.cpp ) diff --git a/source/sw/src/anim.cpp b/source/sw/src/anim.cpp index 052822e0c..de3e0e216 100644 --- a/source/sw/src/anim.cpp +++ b/source/sw/src/anim.cpp @@ -226,7 +226,7 @@ void AnimZilla(int frame, int numframes) } } -unsigned char *LoadAnm(short anim_num) +unsigned char *LoadAnm(short anim_num, int *lengthp) { int length; unsigned char *animbuf, *palptr; @@ -240,13 +240,16 @@ unsigned char *LoadAnm(short anim_num) ANIMnum = anim_num; // lock it - + + int file = fileSystem.FindFile(ANIMname[ANIMnum]); + if (file < 0) return nullptr; + *lengthp = length = fileSystem.FileLength(file); + if (anm_ptr[anim_num] == 0) { - auto handle = kopenFileReader(ANIMname[ANIMnum], 0); + auto handle = fileSystem.OpenFileReader(file); if (!handle.isOpen()) return NULL; - length = handle.GetLength(); buffer.Resize(length + sizeof(anim_t)); anm_ptr[anim_num] = (anim_t*)buffer.Data(); @@ -280,14 +283,10 @@ playanm(short anim_num) DSPRINTF(ds,"PlayAnm"); MONO_PRINT(ds); - animbuf = LoadAnm(anim_num); + animbuf = LoadAnm(anim_num, &length); if (!animbuf) return; - // [JM] Temporary, needed to get the file's length for ANIM_LoadAnim. !CHECKME! - length = kfilesize(ANIMname[ANIMnum], 0); - if (length == -1) return; - DSPRINTF(ds,"PlayAnm - Palette Stuff"); MONO_PRINT(ds); @@ -320,12 +319,12 @@ playanm(short anim_num) switch (ANIMnum) { case ANIM_INTRO: - if (I_GeneralTrigger() || quitevent) + if (I_GeneralTrigger()) I_GeneralTriggerClear(); goto ENDOFANIMLOOP; break; case ANIM_SERP: - if (I_EscapeTrigger() || quitevent) + if (I_EscapeTrigger()) I_EscapeTriggerClear(); goto ENDOFANIMLOOP; break; diff --git a/source/sw/src/anim.h b/source/sw/src/anim.h index c5bc4c410..b44ca1556 100644 --- a/source/sw/src/anim.h +++ b/source/sw/src/anim.h @@ -30,6 +30,6 @@ BEGIN_SW_NS #define ANIM_SUMO 2 #define ANIM_ZILLA 3 -unsigned char *LoadAnm(short anim_num); +unsigned char *LoadAnm(short anim_num, int *); void playanm(short anim_num); END_SW_NS diff --git a/source/sw/src/border.cpp b/source/sw/src/border.cpp index 33398e44b..ac5609702 100644 --- a/source/sw/src/border.cpp +++ b/source/sw/src/border.cpp @@ -441,10 +441,9 @@ static void BorderSetView(PLAYERp, int *Xdim, int *Ydim, int *ScreenSize) y = DIV2(*Ydim) - DIV2((*ScreenSize **Ydim) / *Xdim); y2 = y + ((*ScreenSize **Ydim) / *Xdim) - 1; - if (ydim == 480 && gs.BorderNum == 2) - { - y2+=2; - } + // avoid a one-pixel tall HOM + if (gs.BorderNum == BORDER_BAR) + ++y2; // global windowxy1, windowxy2 coords set here videoSetViewableArea(x, y, x2, y2); diff --git a/source/sw/src/cheats.cpp b/source/sw/src/cheats.cpp index e44e2ff0b..529d38fd1 100644 --- a/source/sw/src/cheats.cpp +++ b/source/sw/src/cheats.cpp @@ -45,6 +45,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "control.h" #include "gamecontrol.h" +#include "gstrings.h" //#include "inv.h" BEGIN_SW_NS @@ -104,8 +105,7 @@ void MapCheat(PLAYERp pp, const char *) else MapSetAll2D(0xFF); - sprintf(ds, "AUTOMAPPING %s", automapping ? "ON" : "OFF" ); - PutStringInfo(pp, ds); + PutStringInfo(pp, GStrings(automapping ? "TXT_AMON" : "TXT_AMOFF")); } void LocCheat(PLAYERp pp, const char *) @@ -123,7 +123,7 @@ void GunsCheat(PLAYERp pp, const char *cheat_string) unsigned int i; short gAmmo[10] = {0,9,12,20,3,6,5,5,10,1}; const char *cp = cheat_string; - const char *str = "GIVEN WEAPON %1d"; + const char *str = "TXT_GIVENW"; int gunnum, x; USERp u; @@ -142,17 +142,16 @@ void GunsCheat(PLAYERp pp, const char *cheat_string) if (TEST(p->WpnFlags, BIT(gunnum-1)) == 0) p->WpnFlags += BIT(gunnum-2) << 1; else - str = "ADD AMMO TO WEAPON %1d"; + str = "TXTS_AMMOW"; p->WpnAmmo[gunnum-1] += x; if (p->WpnAmmo[gunnum-1] > DamageData[gunnum-1].max_ammo) { p->WpnAmmo[gunnum-1] = DamageData[gunnum-1].max_ammo; - str = ""; + str = nullptr; } PlayerUpdateWeapon(p, u->WeaponNum); } - sprintf(ds, str, gunnum); - PutStringInfo(pp, ds); + if (str) PutStringInfo(pp, FStringf("%s %d", GStrings(str), gunnum)); } void WeaponCheat(PLAYERp pp, const char *) @@ -195,16 +194,13 @@ void GodCheat(PLAYERp pp, const char *) // GodMode ^= 1; - sprintf(ds, "GOD MODE %s", GodMode ? "ON" : "OFF"); - PutStringInfo(pp, ds); + PutStringInfo(pp, GStrings(GodMode? "GOD MODE: ON" : "GOD MODE: OFF")); } void ClipCheat(PLAYERp pp, const char *) { FLIP(pp->Flags, PF_CLIP_CHEAT); - - sprintf(ds, "NO CLIP MODE %s", TEST(pp->Flags, PF_CLIP_CHEAT) ? "ON" : "OFF"); - PutStringInfo(pp, ds); + PutStringInfo(pp, GStrings(TEST(pp->Flags, PF_CLIP_CHEAT) ? "CLIPPING: OFF" : "CLIPPING: ON"));; } void WarpCheat(PLAYERp pp, const char *cheat_string) @@ -233,7 +229,7 @@ void WarpCheat(PLAYERp pp, const char *cheat_string) Level = level_num; ExitLevel = TRUE; - sprintf(ds, "ENTERING %1d", Level); + sprintf(ds, "%s %1d", GStrings("TXT_ENTERING"), Level); PutStringInfo(pp, ds); } @@ -284,15 +280,15 @@ void ItemCheat(PLAYERp pp, const char *cheat_string) VOID HealCheat(PLAYERp pp, const char *cheat_string) { short pnum; - const char *str = ""; + const char *str = nullptr; TRAVERSE_CONNECT(pnum) { if (User[Player[pnum].PlayerSprite]->Health < pp->MaxHealth) - str = "ADDED HEALTH"; + str = "TXTS_ADDEDHEALTH"; User[Player[pnum].PlayerSprite]->Health += 25; } - PutStringInfo(pp, str); + if (str) PutStringInfo(pp, GStrings(str)); } VOID SortKeyCheat(PLAYERp pp, const char *sKey) @@ -359,7 +355,7 @@ VOID KeysCheat(PLAYERp pp, const char *cheat_string) PLAYERp p; short pnum; const char *cp = cheat_string; - const char *str = "Given all keys"; + const char *str = "TXT_GIVEKEY"; int keynum = 0; cp += sizeof("swkey")-1; @@ -378,21 +374,17 @@ VOID KeysCheat(PLAYERp pp, const char *cheat_string) if (p->HasKey[keynum-1] == FALSE) { p->HasKey[keynum-1] = TRUE; // cards: 0=red 1=blue 2=green 3=yellow | keys: 4=gold 5=silver 6=bronze 7=red - str = "Given %s"; + str = "TXT_KEYGIVEN"; } else { p->HasKey[keynum-1] = FALSE; - str = "Removed %s"; + str = "TXT_KEYREMOVED"; } } } PlayerUpdateKeys(pp); - if (keynum == 0) - sprintf(ds, str); - else - sprintf(ds, str, CheatKeyType); - PutStringInfo(pp, ds); + PutStringInfo(pp, GStrings(str)); } void EveryCheatToggle(PLAYERp pp, const char *cheat_string) @@ -402,9 +394,6 @@ void EveryCheatToggle(PLAYERp pp, const char *cheat_string) WeaponCheat(pp, cheat_string); GodCheat(pp, cheat_string); ItemCheat(pp, cheat_string); - - sprintf(ds, "EVERY CHEAT %s", EveryCheat ? "ON" : "OFF"); - PutStringInfo(pp, ds); } void GeorgeFunc(PLAYERp pp, char *) @@ -521,7 +510,7 @@ void CheatInput(void) if (Skill >= 3) { - PutStringInfo(Player, "You're too skillful to cheat\n"); + PutStringInfo(Player, GStrings("TXTS_TOOSKILLFUL")); return; } } diff --git a/source/sw/src/common_game.h b/source/sw/src/common_game.h index c7c0248b0..6b4b207b3 100644 --- a/source/sw/src/common_game.h +++ b/source/sw/src/common_game.h @@ -65,10 +65,6 @@ BEGIN_SW_NS #define SETUPPROGRAMNAME ("Shadow Warrior Setup") #define SETUPPROGRAMVERSION ("1.2") -#define GAMENAME "Shadow Warrior" -#define GAMELAUNCHER ("SW.EXE") -#define GAMETOTYPE ("SW") - #define MENUFOOTER "Esc Exits  Move ÄÙ Selects\0" #define COMMITLAUNCHER ("COMMIT.EXE") diff --git a/source/sw/src/console.cpp b/source/sw/src/console.cpp index e9228f835..b6afca650 100644 --- a/source/sw/src/console.cpp +++ b/source/sw/src/console.cpp @@ -66,6 +66,7 @@ BEGIN_SW_NS SWBOOL SpriteInfo = FALSE; extern SWBOOL QuitFlag; +extern SWBOOL MultiPlayQuitFlag; // FUNCTION PROTOTYPES /////////////////////////////////////////////////////////////////////// void CON_ProcessOptions(void); @@ -249,38 +250,6 @@ SWBOOL IsCommand(const char *str) return FALSE; } -// -// Sends a message to the user quote array -// - -void CON_Message(const char *message, ...) -{ - va_list argptr; - - va_start(argptr,message); - vsprintf(&con_message[0],message,argptr); - va_end(argptr); - - // Send message to user quote array for immediate display - adduserquote(&con_message[0]); -} - -// -// Sends a message to the console quote array -// - -void CON_ConMessage(const char *message, ...) -{ - va_list argptr; - - va_start(argptr,message); - vsprintf(&con_message[0],message,argptr); - va_end(argptr); - - // Send message to user quote array for immediate display - addconquote(&con_message[0]); -} - // // Stores user arguments passed in on the command line for later inspection // @@ -388,7 +357,7 @@ void CON_ProcessUserCommand(void) } if (ConPanel) - CON_ConMessage("Syntax Error or Command not enabled!"); + OSD_Printf("Syntax Error or Command not enabled!"); } // @@ -436,7 +405,7 @@ SWBOOL CheckValidSprite(short SpriteNum) { if (SpriteNum < 0 || SpriteNum > 6144) { - CON_ConMessage("ERROR: Sprite %d is out of range.",SpriteNum); + OSD_Printf("ERROR: Sprite %d is out of range.",SpriteNum); return FALSE; } return TRUE; @@ -451,7 +420,7 @@ void CON_GetHelp(void) if (sscanf(MessageInputString,"%s %s",base,command) < 2) { - CON_ConMessage("Usage: help [keyword]"); + OSD_Printf("Usage: help [keyword]"); return; } @@ -459,25 +428,25 @@ void CON_GetHelp(void) if (!strcmp(command, "xrepeat")) { - CON_ConMessage("Usage: xrepeat [repeat value 0-255],"); - CON_ConMessage(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); + OSD_Printf("Usage: xrepeat [repeat value 0-255],"); + OSD_Printf(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); return; } else if (!strcmp(command, "yrepeat")) { - CON_ConMessage("Usage: yrepeat [repeat value 0-255],"); - CON_ConMessage(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); + OSD_Printf("Usage: yrepeat [repeat value 0-255],"); + OSD_Printf(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); return; } else if (!strcmp(command, "translucent")) { - CON_ConMessage("Usage: translucent [OFF/ON 0-1],"); - CON_ConMessage(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); + OSD_Printf("Usage: translucent [OFF/ON 0-1],"); + OSD_Printf(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); return; } else { - CON_ConMessage("No help was located on that subject."); + OSD_Printf("No help was located on that subject."); } } @@ -512,9 +481,9 @@ void CON_ModXrepeat(void) } } if (op2 == -1) - CON_ConMessage("Xrepeat set to %d for all u->ID's for all sprites.",op1); + OSD_Printf("Xrepeat set to %d for all u->ID's for all sprites.",op1); else - CON_ConMessage("Xrepeat set to %d for u->ID = %d for all sprites.",op1,op2); + OSD_Printf("Xrepeat set to %d for u->ID = %d for all sprites.",op1,op2); } else { @@ -525,7 +494,7 @@ void CON_ModXrepeat(void) if (!CheckValidSprite(op3)) return; sp->xrepeat = op1; - CON_ConMessage("Xrepeat set to %d for sprite %d.",op1,op3); + OSD_Printf("Xrepeat set to %d for sprite %d.",op1,op3); } } @@ -561,9 +530,9 @@ void CON_ModYrepeat(void) } } if (op2 == -1) - CON_ConMessage("Yrepeat set to %d for all u->ID's for all sprites.",op1); + OSD_Printf("Yrepeat set to %d for all u->ID's for all sprites.",op1); else - CON_ConMessage("Yrepeat set to %d for u->ID = %d for all sprites.",op1,op2); + OSD_Printf("Yrepeat set to %d for u->ID = %d for all sprites.",op1,op2); } else { @@ -574,7 +543,7 @@ void CON_ModYrepeat(void) if (!CheckValidSprite(op3)) return; sp->yrepeat = op1; - CON_ConMessage("Yrepeat set to %d for sprite %d.",op1,op3); + OSD_Printf("Yrepeat set to %d for sprite %d.",op1,op3); } } @@ -601,12 +570,12 @@ void CON_ModTranslucent(void) if (TEST(sp->cstat,CSTAT_SPRITE_TRANSLUCENT)) { RESET(sp->cstat,CSTAT_SPRITE_TRANSLUCENT); - CON_ConMessage("Translucence RESET for sprite %d.",op1); + OSD_Printf("Translucence RESET for sprite %d.",op1); } else { SET(sp->cstat,CSTAT_SPRITE_TRANSLUCENT); - CON_ConMessage("Translucence SET for sprite %d.",op1); + OSD_Printf("Translucence SET for sprite %d.",op1); } } @@ -627,7 +596,7 @@ void CON_SoundTest(void) if (op1 < 0 || op1 >= DIGI_MAX) { - CON_ConMessage("Sound number out of range."); + OSD_Printf("Sound number out of range."); return; } @@ -649,7 +618,7 @@ void CON_Reverb(void) return; } - CON_ConMessage("Reverb is now set to %d.",op1); + OSD_Printf("Reverb is now set to %d.",op1); COVER_SetReverb(op1); pp->Reverb = op1; } @@ -663,10 +632,10 @@ void CON_Heap(void) void *testheap; totalmemory = Z_AvailHeap(); - CON_ConMessage("Total heap at game startup = %d", TotalMemory); - CON_ConMessage("ActualHeap reserved for non-cache use = %d", ActualHeap); - CON_ConMessage("Total unallocated blocks in bytes minus reserved heap = %d", totalmemory); - CON_ConMessage("NOTE: Allocation exceeding ActualHeap will result in out of memory"); + OSD_Printf("Total heap at game startup = %d", TotalMemory); + OSD_Printf("ActualHeap reserved for non-cache use = %d", ActualHeap); + OSD_Printf("Total unallocated blocks in bytes minus reserved heap = %d", totalmemory); + OSD_Printf("NOTE: Allocation exceeding ActualHeap will result in out of memory"); // Find remaining heap space unused i = ActualHeap; while(i>0) @@ -676,10 +645,10 @@ void CON_Heap(void) i-=1024L; // Decrease in 1k increments else { - CON_ConMessage("Heap test result (+ or - 1k):"); - CON_ConMessage("============================="); - CON_ConMessage("Unallocated heap space remaining = %d",i); - CON_ConMessage("Unallocated heap space used = %d",ActualHeap - i); + OSD_Printf("Heap test result (+ or - 1k):"); + OSD_Printf("============================="); + OSD_Printf("Unallocated heap space remaining = %d",i); + OSD_Printf("Unallocated heap space used = %d",ActualHeap - i); FreeMem(testheap); i=0; // Beam us out of here Scotty! } @@ -687,7 +656,7 @@ void CON_Heap(void) if(ActualHeap < 50000L) { - CON_ConMessage("ALERT: Memory is critically low!"); + OSD_Printf("ALERT: Memory is critically low!"); } */ } @@ -996,14 +965,14 @@ void CON_Cache(void) } } - CON_ConMessage("/////////////////////////////////////////////"); - CON_ConMessage("Current Memory Consumption:"); - CON_ConMessage("Total Tiles = %d",tottiles); - CON_ConMessage("Total Sprites = %d",totsprites); - CON_ConMessage("Total Actors = %d",totactors); - CON_ConMessage("Total Memory = %d",(tottiles+totsprites+totactors)); - CON_ConMessage("Total with LoWang = %d",(tottiles+totsprites+totactors+TileRangeMem(1024))); - CON_ConMessage("/////////////////////////////////////////////"); + OSD_Printf("/////////////////////////////////////////////"); + OSD_Printf("Current Memory Consumption:"); + OSD_Printf("Total Tiles = %d",tottiles); + OSD_Printf("Total Sprites = %d",totsprites); + OSD_Printf("Total Actors = %d",totactors); + OSD_Printf("Total Memory = %d",(tottiles+totsprites+totactors)); + OSD_Printf("Total with LoWang = %d",(tottiles+totsprites+totactors+TileRangeMem(1024))); + OSD_Printf("/////////////////////////////////////////////"); } @@ -1013,11 +982,11 @@ void CON_SpriteInfo(void) if (SpriteInfo > 2) SpriteInfo = 0; if (SpriteInfo == 0) - CON_ConMessage("Sprite information is OFF."); + OSD_Printf("Sprite information is OFF."); else if (SpriteInfo == 1) - CON_ConMessage("Sprite information is ON (Brief Mode)."); + OSD_Printf("Sprite information is ON (Brief Mode)."); else - CON_ConMessage("Sprite information is ON (Verbose Mode)."); + OSD_Printf("Sprite information is ON (Verbose Mode)."); } void CON_KillSprite(void) @@ -1044,14 +1013,14 @@ void CON_KillSprite(void) if (!u->PlayerP) SetSuicide(i); } - CON_ConMessage("Killed all sprites except Players."); + OSD_Printf("Killed all sprites except Players."); } else { if (!CheckValidSprite(op1)) return; SetSuicide(op1); - CON_ConMessage("Killed sprite %d.",op1); + OSD_Printf("Killed sprite %d.",op1); } } @@ -1073,15 +1042,15 @@ void CON_SpriteDetail(void) if (!CheckValidSprite(op1)) return; auto const sp = (uspritetype const *)&sprite[op1]; - CON_ConMessage("x = %d, y = %d, z = %d",sp->x,sp->y,sp->z); - CON_ConMessage("cstat = %d, picnum = %d",sp->cstat,sp->picnum); - CON_ConMessage("shade = %d, pal = %d, clipdist = %d",sp->shade,sp->pal,sp->clipdist); - CON_ConMessage("xrepeat = %d, yrepeat = %d",sp->xrepeat, sp->yrepeat); - CON_ConMessage("xoffset = %d, yoffset = %d",sp->xoffset, sp->yoffset); - CON_ConMessage("sectnum = %d, statnum = %d",sp->sectnum, sp->statnum); - CON_ConMessage("ang = %d, owner = %d",sp->ang,sp->owner); - CON_ConMessage("xvel = %d, yvel = %d, zvel = %d",sp->xvel,sp->yvel,sp->zvel); - CON_ConMessage("lotag = %d, hitag = %d, extra = %d",sp->lotag,sp->hitag,sp->extra); + OSD_Printf("x = %d, y = %d, z = %d",sp->x,sp->y,sp->z); + OSD_Printf("cstat = %d, picnum = %d",sp->cstat,sp->picnum); + OSD_Printf("shade = %d, pal = %d, clipdist = %d",sp->shade,sp->pal,sp->clipdist); + OSD_Printf("xrepeat = %d, yrepeat = %d",sp->xrepeat, sp->yrepeat); + OSD_Printf("xoffset = %d, yoffset = %d",sp->xoffset, sp->yoffset); + OSD_Printf("sectnum = %d, statnum = %d",sp->sectnum, sp->statnum); + OSD_Printf("ang = %d, owner = %d",sp->ang,sp->owner); + OSD_Printf("xvel = %d, yvel = %d, zvel = %d",sp->xvel,sp->yvel,sp->zvel); + OSD_Printf("lotag = %d, hitag = %d, extra = %d",sp->lotag,sp->hitag,sp->extra); } void CON_UserDetail(void) @@ -1106,19 +1075,19 @@ void CON_UserDetail(void) if (!u) return; - CON_ConMessage("State = %p, Rot = %p",u->State,u->Rot); - CON_ConMessage("StateStart = %p, StateEnd = %p",u->StateStart,u->StateEnd); - CON_ConMessage("ActorActionFunc = %p",u->ActorActionFunc); - CON_ConMessage("ActorActionSet = %p",u->ActorActionSet); - CON_ConMessage("Personality = %p",u->Personality); - CON_ConMessage("Attrib = %p",u->Attrib); - CON_ConMessage("Flags = %d, Flags2 = %d, Tics = %d",u->Flags,u->Flags2,u->Tics); - CON_ConMessage("RotNum = %d, ID = %d",u->RotNum,u->ID); - CON_ConMessage("Health = %d, MaxHealth = %d",u->Health,u->MaxHealth); - CON_ConMessage("LastDamage = %d, PainThreshold = %d",u->LastDamage,u->PainThreshold); - CON_ConMessage("jump_speed = %d, jump_grav = %d",u->jump_speed,u->jump_grav); - CON_ConMessage("xchange = %d, ychange = %d, zchange = %d",u->xchange,u->ychange,u->zchange); - CON_ConMessage("ret = %d, WaitTics = %d, spal = %d",u->ret,u->WaitTics,u->spal); + OSD_Printf("State = %p, Rot = %p",u->State,u->Rot); + OSD_Printf("StateStart = %p, StateEnd = %p",u->StateStart,u->StateEnd); + OSD_Printf("ActorActionFunc = %p",u->ActorActionFunc); + OSD_Printf("ActorActionSet = %p",u->ActorActionSet); + OSD_Printf("Personality = %p",u->Personality); + OSD_Printf("Attrib = %p",u->Attrib); + OSD_Printf("Flags = %d, Flags2 = %d, Tics = %d",u->Flags,u->Flags2,u->Tics); + OSD_Printf("RotNum = %d, ID = %d",u->RotNum,u->ID); + OSD_Printf("Health = %d, MaxHealth = %d",u->Health,u->MaxHealth); + OSD_Printf("LastDamage = %d, PainThreshold = %d",u->LastDamage,u->PainThreshold); + OSD_Printf("jump_speed = %d, jump_grav = %d",u->jump_speed,u->jump_grav); + OSD_Printf("xchange = %d, ychange = %d, zchange = %d",u->xchange,u->ychange,u->zchange); + OSD_Printf("ret = %d, WaitTics = %d, spal = %d",u->ret,u->WaitTics,u->spal); } void CON_Quit(void) @@ -1142,7 +1111,7 @@ void CON_MultiNameChange(void) void CON_LoadSetup(void) { - CON_ConMessage("JonoF: Maybe later"); + OSD_Printf("JonoF: Maybe later"); } const char *damagename[] = @@ -1190,34 +1159,34 @@ void CON_DamageData(void) if (op1 < -1 || op1 > 46) { - CON_ConMessage("Damage Data index is out of range."); + OSD_Printf("Damage Data index is out of range."); return; } if (!strcmp(field,"damage_lo")) { DamageData[op1].damage_lo = op2; - CON_ConMessage("DamageData[%s].damage_lo = %d",damagename[op1],op2); + OSD_Printf("DamageData[%s].damage_lo = %d",damagename[op1],op2); } else if (!strcmp(field,"damage_hi")) { DamageData[op1].damage_hi = op2; - CON_ConMessage("DamageData[%s].damage_hi = %d",damagename[op1],op2); + OSD_Printf("DamageData[%s].damage_hi = %d",damagename[op1],op2); } else if (!strcmp(field,"radius")) { DamageData[op1].radius = op2; - CON_ConMessage("DamageData[%s].radius = %d",damagename[op1],op2); + OSD_Printf("DamageData[%s].radius = %d",damagename[op1],op2); } else if (!strcmp(field,"max_ammo")) { DamageData[op1].max_ammo = op2; - CON_ConMessage("DamageData[%s].max_ammo = %d",damagename[op1],op2); + OSD_Printf("DamageData[%s].max_ammo = %d",damagename[op1],op2); } else if (!strcmp(field,"min_ammo")) { DamageData[op1].min_ammo = op2; - CON_ConMessage("DamageData[%s].min_ammo = %d",damagename[op1],op2); + OSD_Printf("DamageData[%s].min_ammo = %d",damagename[op1],op2); } if (!strcmp(field,"show")) { @@ -1226,17 +1195,17 @@ void CON_DamageData(void) for (i=op2; i<=op2+10; i+=2) { if (i<47) - CON_ConMessage("[%d] = %s [%d] = %s",i,damagename[i],i+1,damagename[i+1]); + OSD_Printf("[%d] = %s [%d] = %s",i,damagename[i],i+1,damagename[i+1]); } } else { - CON_ConMessage(" "); - CON_ConMessage("Item = %s:",damagename[op1]); - CON_ConMessage("damage_lo = %d, damag_hi = %d",DamageData[op1].damage_lo,DamageData[op1].damage_hi); - CON_ConMessage("radius = %u",DamageData[op1].radius); - CON_ConMessage("min_ammo = %d, max_ammo = %d",DamageData[op1].min_ammo,DamageData[op1].max_ammo); - CON_ConMessage(" "); + OSD_Printf(" "); + OSD_Printf("Item = %s:",damagename[op1]); + OSD_Printf("damage_lo = %d, damag_hi = %d",DamageData[op1].damage_lo,DamageData[op1].damage_hi); + OSD_Printf("radius = %u",DamageData[op1].radius); + OSD_Printf("min_ammo = %d, max_ammo = %d",DamageData[op1].min_ammo,DamageData[op1].max_ammo); + OSD_Printf(" "); } } } @@ -1278,13 +1247,13 @@ void CON_Tweak(void) { extern short ADJUST; ADJUST = op1; - CON_ConMessage("Zvelocity ADJUST set to %d.",op1); + OSD_Printf("Zvelocity ADJUST set to %d.",op1); } else if (!strcmp(command,"adjustv")) { extern int ADJUSTV; ADJUSTV = op1; - CON_ConMessage("Zvelocity ADJUSTV set to %d.",op1); + OSD_Printf("Zvelocity ADJUSTV set to %d.",op1); } } @@ -1308,20 +1277,20 @@ void CON_CheckHeap(void) switch( _heapchk() ) { case _HEAPOK: - CON_ConMessage( "OK - heap is good\n" ); + OSD_Printf( "OK - heap is good\n" ); break; case _HEAPEMPTY: - CON_ConMessage( "OK - heap is empty\n" ); + OSD_Printf( "OK - heap is empty\n" ); break; case _HEAPBADBEGIN: - CON_ConMessage( "ERROR - heap is damaged\n" ); + OSD_Printf( "ERROR - heap is damaged\n" ); break; case _HEAPBADNODE: - CON_ConMessage( "ERROR - bad node in heap\n" ); + OSD_Printf( "ERROR - bad node in heap\n" ); break; } */ - CON_ConMessage("JonoF: Not now"); + OSD_Printf("JonoF: Not now"); } /* @@ -1363,7 +1332,7 @@ void heap_dump( void ) void CON_DumpHeap(void) { //heap_dump(); // Dump it. - CON_ConMessage("JonoF: Not now"); + OSD_Printf("JonoF: Not now"); } void CON_ShowMirror(void) @@ -1381,21 +1350,21 @@ void CON_ShowMirror(void) if (op1 < 0 || op1 > 9) { - CON_ConMessage("Mirror number is out of range!"); + OSD_Printf("Mirror number is out of range!"); return; } - CON_ConMessage("camera is the ST1 sprite used as the view spot"); - CON_ConMessage("camspite is the SpriteNum of the drawtotile tile in editart"); - CON_ConMessage("camspic is the tile number of the drawtotile in editart"); - CON_ConMessage("iscamera is whether or not this mirror is a camera type"); - CON_ConMessage(" "); - CON_ConMessage("mirror[%d].mirrorwall = %d",op1,mirror[op1].mirrorwall); - CON_ConMessage("mirror[%d].mirrorsector = %d",op1,mirror[op1].mirrorsector); - CON_ConMessage("mirror[%d].camera = %d",op1,mirror[op1].camera); - CON_ConMessage("mirror[%d].camsprite = %d",op1,mirror[op1].camsprite); - CON_ConMessage("mirror[%d].campic = %d",op1,mirror[op1].campic); - CON_ConMessage("mirror[%d].iscamera = %d",op1,mirror[op1].ismagic); + OSD_Printf("camera is the ST1 sprite used as the view spot"); + OSD_Printf("camspite is the SpriteNum of the drawtotile tile in editart"); + OSD_Printf("camspic is the tile number of the drawtotile in editart"); + OSD_Printf("iscamera is whether or not this mirror is a camera type"); + OSD_Printf(" "); + OSD_Printf("mirror[%d].mirrorwall = %d",op1,mirror[op1].mirrorwall); + OSD_Printf("mirror[%d].mirrorsector = %d",op1,mirror[op1].mirrorsector); + OSD_Printf("mirror[%d].camera = %d",op1,mirror[op1].camera); + OSD_Printf("mirror[%d].camsprite = %d",op1,mirror[op1].camsprite); + OSD_Printf("mirror[%d].campic = %d",op1,mirror[op1].campic); + OSD_Printf("mirror[%d].iscamera = %d",op1,mirror[op1].ismagic); } void CON_DumpSoundList(void) @@ -1403,7 +1372,7 @@ void CON_DumpSoundList(void) extern void DumpSounds(void); DumpSounds(); - CON_Message("Sounds dumped to dbg.foo"); + OSD_Printf("Sounds dumped to dbg.foo"); } diff --git a/source/sw/src/d_menu.cpp b/source/sw/src/d_menu.cpp new file mode 100644 index 000000000..3c431eabc --- /dev/null +++ b/source/sw/src/d_menu.cpp @@ -0,0 +1,308 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2016 EDuke32 developers and contributors +Copyright (C) 2019 Christoph Oelckers + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- + +#include "ns.h" // Must come before everything else! +#include "build.h" +#include "osd.h" + +#include "keys.h" +#include "names2.h" +#include "panel.h" +#include "game.h" +#include "tags.h" +#include "sector.h" +#include "sprite.h" +#include "weapon.h" +#include "player.h" +#include "jsector.h" +#include "control.h" +#include "menus.h" +#include "sw_strs.h" +#include "pal.h" +#include "demo.h" +#include "input.h" +#include "keydef.h" + +#include "gamecontrol.h" +#include "gamedefs.h" +#include "config.h" +#include "network.h" +#include "fx_man.h" +#include "music.h" +#include "text.h" +#include "version.h" +#include "network.h" + +#include "colormap.h" +#include "config.h" +#include "menu/menu.h" + +#include "../../glbackend/glbackend.h" + + +BEGIN_SW_NS + +int handle1; + +void Menu_Init(void) +{ + + +} + +//---------------------------------------------------------------------------- +// +// Implements the native looking menu used for the main menu +// and the episode/skill selection screens, i.e. the parts +// that need to look authentic +// +//---------------------------------------------------------------------------- + +class SWMainMenu : public DListMenu +{ + void Ticker() override + { + // Dynamically enable and disable the save option + for (unsigned e = 0; e < mDesc->mItems.Size(); ++e) + { + auto entry = mDesc->mItems[e]; + if (entry->GetAction(nullptr) == NAME_SaveGameMenu) + { + entry->mEnabled = gi->CanSave(); + } + } + } + + void PreDraw() override + { + rotatesprite(160 << 16, 15 << 16, 65536, 0, pic_shadow_warrior, + m_defshade, 0, ROTATE_SPRITE_SCREEN_CLIP, 0, 0, xdim - 1, ydim - 1); + } +}; + +static bool DidOrderSound; +static int zero = 0; +class SWOrderMenu : public DImageScrollerMenu +{ +public: + SWOrderMenu() + { + if (SW_SHAREWARE && !DidOrderSound) + { + DidOrderSound = true; + int choose_snd = STD_RANDOM_RANGE(1000); + if (choose_snd > 500) + PlaySound(DIGI_WANGORDER1, &zero, &zero, &zero, v3df_dontpan); + else + PlaySound(DIGI_WANGORDER2, &zero, &zero, &zero, v3df_dontpan); + } + } +}; + +//---------------------------------------------------------------------------- +// +// Menu related game interface functions +// +//---------------------------------------------------------------------------- + +void GameInterface::DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) +{ + short w, h; + switch (fontnum) + { + case NIT_BigFont: + MNU_MeasureStringLarge(text, &w, &h); + if (flags & LMF_Centered) xpos -= w/2; + MNU_DrawStringLarge(short(xpos), short(ypos), text, state == NIT_InactiveState? 20 : 0); + break; + + case NIT_SmallFont: + MNU_MeasureString(text, &w, &h); + if (flags & LMF_Centered) xpos -= w/2; + MNU_DrawString(short(xpos), short(ypos), text, state == NIT_InactiveState? 20 : 0, 16); + break; + + case NIT_TinyFont: + MNU_MeasureSmallString(text, &w, &h); + if (flags & LMF_Centered) xpos -= w/2; + MNU_DrawSmallString(short(xpos), short(ypos), text, state == NIT_InactiveState? 20 : 0, 16); + break; + } + if (state == NIT_SelectedState) + { + int x = int(xpos), y = int(ypos); + int scale = 65536; + short w,h; + + if (text) + { + scale /= 2; + x -= mulscale17(tilesiz[pic_yinyang].x,scale) + 2; + y += 4; + } + else + { + scale -= (1<<13); + x -= ((tilesiz[pic_yinyang].x) / 2) - 3; + y += 8; + } + + rotatesprite(x << 16, y << 16, + scale, 0, pic_yinyang, 2, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); + } +} + + +void GameInterface::MenuOpened() +{ +} + +void GameInterface::MenuSound(EMenuSounds snd) +{ + switch (snd) + { + case CursorSound: + PlaySound(DIGI_STAR,&zero,&zero,&zero,v3df_dontpan); + break; + + case AdvanceSound: + PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan); + break; + + case CloseSound: + PlaySound(DIGI_STARCLINK,&zero,&zero,&zero,v3df_dontpan); + break; + + default: + return; + } +} + +void GameInterface::MenuClosed() +{ + if (!LoadGameOutsideMoveLoop) + { + ResumeGame(); + SetRedrawScreen(&Player[myconnectindex]); + } +} + +extern SWBOOL InMenuLevel; +extern SWBOOL DemoMode; +extern SWBOOL ExitLevel, NewGame; + +bool GameInterface::CanSave() +{ + return (!CommEnabled && numplayers ==1 && !DemoMode && !InMenuLevel && !TEST(Player[myconnectindex].Flags, PF_DEAD)); +} + +void GameInterface::StartGame(FGameStartup& gs) +{ + PLAYERp pp = Player + screenpeek; + int handle = 0; + int zero = 0; + + // always assumed that a demo is playing + + ready2send = 0; + + if (gs.Episode >= 1) + Level = 5; + else + Level = 1; + + DemoPlaying = FALSE; + ExitLevel = TRUE; + NewGame = TRUE; + DemoMode = FALSE; + CameraTestMode = FALSE; + Skill = gs.Skill; + + //InitNewGame(); + + if (Skill == 0) + handle = PlaySound(DIGI_TAUNTAI3,&zero,&zero,&zero,v3df_none); + else if (Skill == 1) + handle = PlaySound(DIGI_NOFEAR,&zero,&zero,&zero,v3df_none); + else if (Skill == 2) + handle = PlaySound(DIGI_WHOWANTSWANG,&zero,&zero,&zero,v3df_none); + else if (Skill == 3) + handle = PlaySound(DIGI_NOPAIN,&zero,&zero,&zero,v3df_none); + + if (handle > FX_Ok) + while (FX_SoundActive(handle)) + handleevents(); +} + +FSavegameInfo GameInterface::GetSaveSig() +{ + return { SAVESIG_SW, MINSAVEVER_SW, SAVEVER_SW }; +} + +void GameInterface::DrawMenuCaption(const DVector2& origin, const char* text) +{ + short w, h; + // Draw the backdrop bar + rotatesprite(10 << 16, (5-3) << 16, 65536, 0, 2427, + 2, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + MNU_MeasureStringLarge(text, &w, &h); + MNU_DrawStringLarge(TEXT_XCENTER(w), 5, text, 1); +} + +void GameInterface::DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) +{ + if (text) + { + short width, height = 0; + MNU_MeasureString("T", &width, &height); + + auto lines = FString(text).Split("\n"); + int y = 100 - (height * lines.Size() / 2); + for (auto& l : lines) + { + short lheight = 0; + MNU_MeasureString(l, &width, &lheight); + int x = 160 - width / 2; + MNU_DrawString(x, y, l, 0, 0); + y += height; + } + } +} + + + +END_SW_NS + +//---------------------------------------------------------------------------- +// +// Class registration +// +//---------------------------------------------------------------------------- + + +static TMenuClassDescriptor _mm("ShadowWarrior.MainMenu"); +static TMenuClassDescriptor _so("ShadowWarrior.OrderMenu"); + +void RegisterSWMenus() +{ + menuClasses.Push(&_mm); + menuClasses.Push(&_so); +} diff --git a/source/sw/src/damage.h b/source/sw/src/damage.h index c395632f8..d2904f8cc 100644 --- a/source/sw/src/damage.h +++ b/source/sw/src/damage.h @@ -26,15 +26,15 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #ifdef DAMAGE_TABLE #define DAMAGE_ENTRY(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon) \ - { init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, NULL, NULL, -1, -1 }, -#define DAMAGE_ENTRY_WPN(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_name, ammo_name, weapon_pickup, ammo_pickup ) \ - { init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_name, ammo_name, weapon_pickup, ammo_pickup }, + { init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, -1, -1 }, +#define DAMAGE_ENTRY_WPN(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_pickup, ammo_pickup ) \ + { init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_pickup, ammo_pickup }, #endif #ifdef DAMAGE_ENUM #define DAMAGE_ENTRY(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon) \ id, -#define DAMAGE_ENTRY_WPN(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_name, ammo_name, weapon_pickup, ammo_pickup ) \ +#define DAMAGE_ENTRY_WPN(id, init_func, damage_lo, damage_hi, radius, max_ammo, min_ammo, with_weapon, weapon_pickup, ammo_pickup ) \ id, #endif @@ -42,15 +42,15 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms // weapon DAMAGE_ENTRY(WPN_FIST, InitWeaponFist, 10, 40, 0, -1, -1, -1) -DAMAGE_ENTRY_WPN(WPN_STAR, InitWeaponStar, 5, 10, 0, 99, 3, -1, "Shurikens", NULL, 9, -1) -DAMAGE_ENTRY_WPN(WPN_SHOTGUN, InitWeaponShotgun, 4, 4, 0, 52, 1, -1, "Riot Gun", "Shotshells", 8, 24) -DAMAGE_ENTRY_WPN(WPN_UZI, InitWeaponUzi, 5, 7, 0, 200, 1, -1, "UZI Submachine Gun", "UZI Clip", 50, 50) -DAMAGE_ENTRY_WPN(WPN_MICRO, InitWeaponMicro, 15, 30, 0, 50, 1, -1, "Missile Launcher", "Missiles", 5, 5) -DAMAGE_ENTRY_WPN(WPN_GRENADE, InitWeaponGrenade, 15, 30, 0, 50, 1, -1, "Grenade Launcher", "Grenade Shells", 6, 8) -DAMAGE_ENTRY_WPN(WPN_MINE, InitWeaponMine, 5, 10, 0, 20, 1, -1, "Sticky Bombs", NULL, 5, -1) -DAMAGE_ENTRY_WPN(WPN_RAIL, InitWeaponRail, 40, 60, 0, 20, 1, -1, "Rail Gun", "Rail Gun Rods", 10, 10) -DAMAGE_ENTRY_WPN(WPN_HOTHEAD, InitWeaponHothead, 10, 25, 0, 80, 1, -1, "Guardian Head", "Firebursts", 30, 60) -DAMAGE_ENTRY_WPN(WPN_HEART, InitWeaponHeart, 75, 100, 0, 5, 1, -1, "Ripper Heart", "Deathcoils", 1, 6) +DAMAGE_ENTRY_WPN(WPN_STAR, InitWeaponStar, 5, 10, 0, 99, 3, -1, 9, -1) +DAMAGE_ENTRY_WPN(WPN_SHOTGUN, InitWeaponShotgun, 4, 4, 0, 52, 1, -1, 8, 24) +DAMAGE_ENTRY_WPN(WPN_UZI, InitWeaponUzi, 5, 7, 0, 200, 1, -1, 50, 50) +DAMAGE_ENTRY_WPN(WPN_MICRO, InitWeaponMicro, 15, 30, 0, 50, 1, -1, 5, 5) +DAMAGE_ENTRY_WPN(WPN_GRENADE, InitWeaponGrenade, 15, 30, 0, 50, 1, -1, 6, 8) +DAMAGE_ENTRY_WPN(WPN_MINE, InitWeaponMine, 5, 10, 0, 20, 1, -1, 5, -1) +DAMAGE_ENTRY_WPN(WPN_RAIL, InitWeaponRail, 40, 60, 0, 20, 1, -1, 10, 10) +DAMAGE_ENTRY_WPN(WPN_HOTHEAD, InitWeaponHothead, 10, 25, 0, 80, 1, -1, 30, 60) +DAMAGE_ENTRY_WPN(WPN_HEART, InitWeaponHeart, 75, 100, 0, 5, 1, -1, 1, 6) DAMAGE_ENTRY(WPN_NAPALM, InitWeaponHothead, 50, 100, 0, 100, 40, WPN_HOTHEAD) DAMAGE_ENTRY(WPN_RING, InitWeaponHothead, 15, 50, 0, 100, 20, WPN_HOTHEAD) @@ -77,7 +77,7 @@ DAMAGE_ENTRY(DMG_GRENADE_EXP, NULL, 70, 140, 6500, -1, -1 DAMAGE_ENTRY(DMG_MINE_EXP, NULL, 85, 115, 6500, -1, -1, -1) DAMAGE_ENTRY(DMG_MINE_SHRAP, NULL, 15, 30, 0, -1, -1, -1) DAMAGE_ENTRY(DMG_MICRO_EXP, NULL, 50, 100, 4500, -1, -1, -1) -DAMAGE_ENTRY_WPN(DMG_NUCLEAR_EXP, NULL, 0, 800, 30000, -1, -1, -1, "Nuclear Warhead", "Heat Seeker Card", 1, 5) +DAMAGE_ENTRY_WPN(DMG_NUCLEAR_EXP, NULL, 0, 800, 30000, -1, -1, -1, 1, 5) DAMAGE_ENTRY(DMG_RADIATION_CLOUD, NULL, 2, 6, 5000, -1, -1, -1) DAMAGE_ENTRY(DMG_FLASHBOMB, NULL, 100, 150, 16384, -1, -1, -1) diff --git a/source/sw/src/demo.cpp b/source/sw/src/demo.cpp index cc4e5e02e..863214725 100644 --- a/source/sw/src/demo.cpp +++ b/source/sw/src/demo.cpp @@ -84,7 +84,6 @@ SWBOOL DemoInitOnce = FALSE; short DemoDebugBufferMax = 1; extern char LevelName[]; -extern char LevelSong[16]; extern uint8_t FakeMultiNumPlayers; extern SWBOOL QuitFlag; @@ -179,7 +178,7 @@ DemoWriteHeader(void) return; strcpy(dh.map_name, LevelName); - strcpy(dh.LevelSong, LevelSong); + strcpy(dh.LevelSong, ""); dh.Level = Level; if (FakeMultiNumPlayers) @@ -238,7 +237,6 @@ DemoReadHeader(void) DREAD(&dh, sizeof(dh), 1, DemoFileIn); strcpy(DemoLevelName, dh.map_name); - strcpy(LevelSong, dh.LevelSong); Level = dh.Level; if (dh.numplayers > 1) { @@ -389,13 +387,6 @@ DemoPlayBack(void) ControlInfo info; int Xdim, Ydim, ScreenSize; - if (SW_SHAREWARE) - { - // code here needs to be similar to RunLevel startup code - PlaySong(LevelSong, -1, TRUE, TRUE); - } - - // Initialize Game part of network code (When ready2send != 0) InitNetVars(); @@ -452,8 +443,6 @@ DemoPlayBack(void) domovethings(); - MNU_CheckForMenus(); - // fast forward and slow mo if (DemoEdit) { @@ -572,8 +561,7 @@ ScenePlayBack(void) if (SW_SHAREWARE) { // code here needs to be similar to RunLevel startup code - strcpy(LevelSong,"yokoha03.mid"); - PlaySong(LevelSong, -1, TRUE, TRUE); + PlaySong(nullptr, "yokoha03.mid", -1); } // IMPORTANT - MUST be right before game loop @@ -621,8 +609,6 @@ ScenePlayBack(void) //movethings(); domovethings(); - - MNU_CheckForMenus(); } // demo is over diff --git a/source/sw/src/demo.h b/source/sw/src/demo.h index 0be471f6a..e0324923f 100644 --- a/source/sw/src/demo.h +++ b/source/sw/src/demo.h @@ -55,7 +55,7 @@ extern int DemoRecCnt; // Can only record 1-player game #if DEMO_FILE_TYPE == DEMO_FILE_GROUP typedef FileReader DFILE; #define DREAD(ptr, size, num, handle) (handle).Read((ptr),(size)*(num)) -#define DOPEN_READ(name) kopenFileReader(name,0) +#define DOPEN_READ(name) fileSystem.OpenFileReader(name,0) #define DCLOSE(handle) ((handle).Close()) #define DF_ERR(f) (!(f).isOpen()) #else diff --git a/source/sw/src/draw.cpp b/source/sw/src/draw.cpp index 84934cff7..930165ce2 100644 --- a/source/sw/src/draw.cpp +++ b/source/sw/src/draw.cpp @@ -56,6 +56,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "interp.h" #include "sector.h" #include "config.h" +#include "menu/menu.h" +#include "swcvar.h" BEGIN_SW_NS @@ -693,7 +695,7 @@ analyzesprites(int viewx, int viewy, int viewz, SWBOOL mirror) tu = User[SpriteNum]; //if(tsp->statnum == STAT_GENERIC_QUEUE) - // CON_ConMessage("tsp->pal = %d",tsp->pal); + // OSD_Printf("tsp->pal = %d",tsp->pal); #if 0 // Brighten up the sprite if set somewhere else to do so @@ -765,7 +767,7 @@ analyzesprites(int viewx, int viewy, int viewz, SWBOOL mirror) //#define DART_REPEAT 6 //#define DART_PIC 2233 - if (gs.Darts) + if (sw_darts) if (tu->ID == 1793 || tsp->picnum == 1793) { tsp->picnum = 2519; @@ -777,7 +779,7 @@ analyzesprites(int viewx, int viewy, int viewz, SWBOOL mirror) #define DART_REPEAT 16 if (tu->ID == STAR1) { - if (gs.Darts) + if (sw_darts) { tsp->picnum = DART_PIC; tsp->ang = NORM_ANGLE(tsp->ang - 512 - 24); @@ -841,7 +843,7 @@ analyzesprites(int viewx, int viewy, int viewz, SWBOOL mirror) } } - if (gs.Darts) + if (sw_darts) if (tsp->statnum == STAT_STAR_QUEUE) { tsp->picnum = DART_PIC; @@ -1039,7 +1041,7 @@ post_analyzesprites(void) void ResizeView(PLAYERp pp) { - if (MenuInputMode || InputMode || HelpInputMode || ConPanel || ConInputMode || PauseKeySet) + if (M_Active() || PauseKeySet) return; if (dimensionmode == 2 || dimensionmode == 5 || dimensionmode == 6) @@ -1069,21 +1071,18 @@ ResizeView(PLAYERp pp) if (buttonMap.ButtonDown(gamefunc_Shrink_Screen)) // && { buttonMap.ClearButton(gamefunc_Shrink_Screen); - SetBorder(pp, gs.BorderNum + 1); - SetRedrawScreen(pp); + G_ChangeHudLayout(-1); } if (buttonMap.ButtonDown(gamefunc_Enlarge_Screen)) // && { buttonMap.ClearButton(gamefunc_Enlarge_Screen); - SetBorder(pp, gs.BorderNum - 1); - SetRedrawScreen(pp); + G_ChangeHudLayout(1); } } } // !JIM! 08/06 -extern SWBOOL UsingMenus; #if 0 void @@ -1417,6 +1416,7 @@ void PrintLocationInfo(PLAYERp pp) SWBOOL DebugSecret = FALSE; void SecretInfo(PLAYERp pp) { + if (!hud_stats) return; #define Y_STEP 7 #define AVERAGEFRAMES 16 int x = windowxy1.x+2; @@ -1665,22 +1665,6 @@ void ResChange(void) } #endif -void ScreenCaptureKeys(void) -{ - if (ConPanel) - return; - - // screen capture - if (inputState.GetKeyStatus(KEYSC_F12)) - { - inputState.ClearKeyStatus(KEYSC_F12); - PauseAction(); - videoCaptureScreen(); - ResumeAction(); - PutStringInfo(Player + myconnectindex, "Screen Captured"); - } -} - void DrawCheckKeys(PLAYERp pp) { extern SWBOOL ResCheat; @@ -1696,8 +1680,6 @@ void DrawCheckKeys(PLAYERp pp) if (!InputMode) ResizeView(pp); - - ScreenCaptureKeys(); } #if 0 @@ -2186,7 +2168,6 @@ drawscreen(PLAYERp pp) int tx, ty, tz,thoriz,pp_siz; short tang,tsectnum; short i,j; - walltype *wal; int tiltlock; int bob_amt = 0; int quake_z, quake_x, quake_y; @@ -2198,6 +2179,8 @@ drawscreen(PLAYERp pp) static short lv_sectnum = -1; static int lv_x, lv_y, lv_z; + int const viewingRange = viewingrange; + if (HelpInputMode) { renderFlushPerms(); @@ -2247,12 +2230,6 @@ drawscreen(PLAYERp pp) PreUpdatePanel(); - if (r_usenewaspect) - { - newaspect_enable = 1; - videoSetCorrectedAspect(); - } - smoothratio = min(max(((int32_t) totalclock - ototalclock) * (65536 / synctics),0),65536); if (!ScreenSavePic) @@ -2283,11 +2260,13 @@ drawscreen(PLAYERp pp) if (tsectnum < 0) { +#if 0 // if we hit an invalid sector move to the last valid position for drawing tsectnum = lv_sectnum; tx = lv_x; ty = lv_y; tz = lv_z; +#endif } else { @@ -2299,7 +2278,7 @@ drawscreen(PLAYERp pp) } // with "last valid" code this should never happen - ASSERT(tsectnum >= 0 && tsectnum <= MAXSECTORS); + // ASSERT(tsectnum >= 0 && tsectnum <= MAXSECTORS); pp->six = tx; pp->siy = ty; @@ -2363,6 +2342,12 @@ drawscreen(PLAYERp pp) thoriz = min(thoriz, PLAYER_HORIZ_MAX); } + if (r_usenewaspect) + { + newaspect_enable = 1; + videoSetCorrectedAspect(); + } + if (FAF_DebugView) videoClearViewableArea(255L); @@ -2387,6 +2372,12 @@ drawscreen(PLAYERp pp) post_analyzesprites(); renderDrawMasks(); + if (r_usenewaspect) + { + newaspect_enable = 0; + renderSetAspect(viewingRange, tabledivide32_noinline(65536 * ydim * 8, xdim * 5)); + } + UpdatePanel(); #define SLIME 2305 @@ -2406,18 +2397,21 @@ drawscreen(PLAYERp pp) i = pp->cursectnum; - show2dsector[i>>3] |= (1<<(i&7)); - wal = &wall[sector[i].wallptr]; - for (j=sector[i].wallnum; j>0; j--,wal++) + if (i >= 0) { - i = wal->nextsector; - if (i < 0) continue; - if (wal->cstat&0x0071) continue; - uint16_t const nextwall = wal->nextwall; - if (nextwall < MAXWALLS && wall[nextwall].cstat&0x0071) continue; - if (sector[i].lotag == 32767) continue; - if (sector[i].ceilingz >= sector[i].floorz) continue; show2dsector[i>>3] |= (1<<(i&7)); + walltype *wal = &wall[sector[i].wallptr]; + for (j=sector[i].wallnum; j>0; j--,wal++) + { + i = wal->nextsector; + if (i < 0) continue; + if (wal->cstat&0x0071) continue; + uint16_t const nextwall = wal->nextwall; + if (nextwall < MAXWALLS && wall[nextwall].cstat&0x0071) continue; + if (sector[i].lotag == 32767) continue; + if (sector[i].ceilingz >= sector[i].floorz) continue; + show2dsector[i>>3] |= (1<<(i&7)); + } } if ((dimensionmode == 5 || dimensionmode == 6) && pp == Player+myconnectindex) @@ -2460,12 +2454,6 @@ drawscreen(PLAYERp pp) SET(sprite[j].cstat, CSTAT_SPRITE_ALIGNMENT_FLOOR); } - if (r_usenewaspect) - { - newaspect_enable = 0; - videoSetCorrectedAspect(); - } - // if doing a screen save don't need to process the rest if (ScreenSavePic) @@ -2503,10 +2491,8 @@ drawscreen(PLAYERp pp) DrawCompass(pp); UpdateMiniBar(pp); - if (UsingMenus) - MNU_DrawMenu(); - else - SecretInfo(pp); + if (!M_Active()) + SecretInfo(pp); videoNextPage(); @@ -2604,7 +2590,7 @@ DrawCompass(PLAYERp pp) start_ang = NORM_CANG(start_ang - 4); flags = ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER; - if (RedrawCompass) + if (RedrawCompass && !M_Active()) { RedrawCompass = FALSE; SET(flags, ROTATE_SPRITE_ALL_PAGES); diff --git a/source/sw/src/game.cpp b/source/sw/src/game.cpp index 71319f971..d2434935b 100644 --- a/source/sw/src/game.cpp +++ b/source/sw/src/game.cpp @@ -94,6 +94,12 @@ Things required to make savegames work: #include "gameconfigfile.h" #include "printf.h" #include "m_argv.h" +#include "debugbreak.h" +#include "menu/menu.h" +#include "z_music.h" +#include "statistics.h" +#include "gstrings.h" +#include "mapinfo.h" //#include "crc32.h" @@ -105,6 +111,8 @@ signed char MNU_InputString(char*, short); SWBOOL IsCommand(const char* str); SWBOOL MNU_StartNetGame(void); +extern SWBOOL MultiPlayQuitFlag; + #if DEBUG #define BETA 0 @@ -170,9 +178,8 @@ extern SWBOOL GamePaused; short screenpeek = 0; SWBOOL NoDemoStartup = FALSE; SWBOOL FirstTimeIntoGame; -extern uint8_t RedBookSong[40]; -SWBOOL BorderAdjust = TRUE; +SWBOOL BorderAdjust = FALSE; SWBOOL LocationInfo = 0; void drawoverheadmap(int cposx, int cposy, int czoom, short cang); int DispFrameRate = FALSE; @@ -207,9 +214,6 @@ const GAME_SET gs_defaults = 0, // Time Limit 0, // Color TRUE, // nuke - "Track??", // waveform track name - FALSE, - TRUE, }; GAME_SET gs; @@ -642,24 +646,17 @@ void TerminateGame(void) } -void LoadLevel(const char *filename) +bool LoadLevel(const char *filename) { - int pos; - if (engineLoadBoard(filename, SW_SHAREWARE ? 1 : 0, (vec3_t *)&Player[0], &Player[0].pang, &Player[0].cursectnum) == -1) { TerminateGame(); -#ifdef RENDERTYPEWIN - { - char msg[256]; - Bsnprintf(msg, 256, "Level not found: %s", filename); - wm_msgbox(apptitle, msg); + Printf("Level not found: %s", filename); + return false; } -#else - printf("Level Not Found: %s\n", filename); -#endif - exit(0); - } + currentLevel = &mapList[Level]; + STAT_NewLevel(currentLevel->labelName); + return true; } void LoadDemoRun(void) @@ -806,7 +803,7 @@ static void SW_FatalEngineError(void) I_Error("There was a problem initialising the Build engine: %s", engineerrstr); } -void InitGame() +bool InitGame() { extern int MovesPerPacket; //void *ReserveMem=NULL; @@ -841,13 +838,8 @@ void InitGame() while (initmultiplayerscycle()) { handleevents(); - if (quitevent) - { - QuitFlag = TRUE; - return; } } - } #else numplayers = 1; myconnectindex = 0; connecthead = 0; connectpoint2[0] = -1; @@ -929,9 +921,13 @@ void InitGame() LoadKVXFromScript("swvoxfil.txt"); // Load voxels from script file LoadPLockFromScript("swplock.txt"); // Get Parental Lock setup info + + LoadCustomInfoFromScript("demolition/swcustom.txt"); // load the internal definitions. These also apply to the shareware version. if (!SW_SHAREWARE) + { LoadCustomInfoFromScript("swcustom.txt"); // Load user customisation information - + } + if (!loaddefinitionsfile(G_DefFile())) buildputs("Definitions file loaded.\n"); userConfig.AddDefs.reset(); @@ -944,7 +940,7 @@ void InitGame() if (UserMapName[0] == '\0') { AnimateCacheCursor(); - LoadLevel("$dozer.map"); + if (!LoadLevel("$dozer.map")) return false; AnimateCacheCursor(); SetupPreCache(); DoTheCache(); @@ -952,7 +948,7 @@ void InitGame() else { AnimateCacheCursor(); - LoadLevel(UserMapName); + if (!LoadLevel(UserMapName)) return false; AnimateCacheCursor(); SetupPreCache(); DoTheCache(); @@ -965,8 +961,7 @@ void InitGame() COVERsetbrightness(0, &palette_data[0][0]); InitFX(); // JBF: do it down here so we get a hold of the window handle - InitMusic(); - + return true; } @@ -987,90 +982,10 @@ TYTAIK16 MID YOKOHA03 MID */ -char LevelSong[16]; short SongLevelNum; -//#ifndef SW_SHAREWARE -LEVEL_INFO LevelInfo[MAX_LEVELS_REG+2] = -{ - {"title.map", "theme.mid", " ", " ", " " }, - {"$bullet.map", "e1l01.mid", "Seppuku Station", "0 : 55", "5 : 00" }, - {"$dozer.map", "e1l03.mid", "Zilla Construction", "4 : 59", "8 : 00" }, - {"$shrine.map", "e1l02.mid", "Master Leep's Temple", "3 : 16", "10 : 00" }, - {"$woods.map", "e1l04.mid", "Dark Woods of the Serpent", "7 : 06", "16 : 00" }, - {"$whirl.map", "yokoha03.mid", "Rising Son", "5 : 30", "10 : 00" }, - {"$tank.map", "nippon34.mid", "Killing Fields", "1 : 46", "4 : 00" }, - {"$boat.map", "execut11.mid", "Hara-Kiri Harbor", "1 : 56", "4 : 00" }, - {"$garden.map", "execut11.mid", "Zilla's Villa", "1 : 06", "2 : 00" }, - {"$outpost.map", "sanai.mid", "Monastery", "1 : 23", "3 : 00" }, - {"$hidtemp.map", "kotec2.mid", "Raider of the Lost Wang", "2 : 05", "4 : 10" }, - {"$plax1.map", "kotec2.mid", "Sumo Sky Palace", "6 : 32", "12 : 00" }, - {"$bath.map", "yokoha03.mid", "Bath House", "10 : 00", "10 : 00" }, - {"$airport.map", "nippon34.mid", "Unfriendly Skies", "2 : 59", "6 : 00" }, - {"$refiner.map", "kotoki12.mid", "Crude Oil", "2 : 40", "5 : 00" }, - {"$newmine.map", "hoshia02.mid", "Coolie Mines", "2 : 48", "6 : 00" }, - {"$subbase.map", "hoshia02.mid", "Subpen 7", "2 : 02", "4 : 00" }, - {"$rock.map", "kotoki12.mid", "The Great Escape", "3 : 18", "6 : 00" }, - {"$yamato.map", "sanai.mid", "Floating Fortress", "11 : 38", "20 : 00" }, - {"$seabase.map", "kotec2.mid", "Water Torture", "5 : 07", "10 : 00" }, - {"$volcano.map", "kotec2.mid", "Stone Rain", "9 : 15", "20 : 00" }, - {"$shore.map", "kotec2.mid", "Shanghai Shipwreck", "3 : 58", "8 : 00" }, - {"$auto.map", "kotec2.mid", "Auto Maul", "4 : 07", "8 : 00" }, - {"tank.map", "kotec2.mid", "Heavy Metal (DM only)", "10 : 00", "10 : 00" }, - {"$dmwoods.map", "kotec2.mid", "Ripper Valley (DM only)", "10 : 00", "10 : 00" }, - {"$dmshrin.map", "kotec2.mid", "House of Wang (DM only)", "10 : 00", "10 : 00" }, - {"$rush.map", "kotec2.mid", "Lo Wang Rally (DM only)", "10 : 00", "10 : 00" }, - {"shotgun.map", "kotec2.mid", "Ruins of the Ronin (CTF)", "10 : 00", "10 : 00" }, - {"$dmdrop.map", "kotec2.mid", "Killing Fields (CTF)", "10 : 00", "10 : 00" }, - {NULL, NULL, NULL, NULL, NULL} -}; -/*#else -LEVEL_INFO LevelInfo[MAX_LEVELS+2] = // Shareware - { - {"title.map", "theme.mid", " ", " ", " " }, - {"$bullet.map", "e1l01.mid", "Seppuku Station", "0 : 55", "5 : 00" }, - {"$dozer.map", "e1l03.mid", "Zilla Construction", "4 : 59", "8 : 00" }, - {"$shrine.map", "e1l02.mid", "Master Leep's Temple", "3 : 16", "10 : 00" }, - {"$woods.map", "e1l04.mid", "Dark Woods of the Serpent", "7 : 06", "16 : 00" }, - {NULL, NULL, NULL, NULL, NULL} - }; -#endif*/ -const char *ThemeSongs[6] = -{ - "THEME.MID", - "ENDLEV3.VOC", - "SERPENT.MID", - "SUMO.MID", - "ZILLA.MID" - "ENDING.MID" -}; - -int ThemeTrack[6] = -{ - 2,3,13,13,13,14 -}; - -char EpisodeNames[3][MAX_EPISODE_NAME_LEN+2] = -{ - "^Enter the Wang", - "^Code of Honor", - "^User Maps", -}; - -char EpisodeSubtitles[3][MAX_EPISODE_SUBTITLE_LEN+1] = -{ - "Four levels (Shareware Version)", - "Eighteen levels (Full Version Only)", - "Select a user map to play", -}; - -char SkillNames[4][MAX_SKILL_NAME_LEN+2] = -{ - "^Tiny grasshopper", - "^I Have No Fear", - "^Who Wants Wang", - "^No Pain, No Gain" -}; +FString ThemeSongs[6]; +int ThemeTrack[6]; void InitNewGame(void) { @@ -1101,15 +1016,12 @@ void FindLevelInfo(char *map_name, short *level) for (j = 1; j <= MAX_LEVELS; j++) { - if (LevelInfo[j].LevelName) + if (Bstrcasecmp(map_name, mapList[j].fileName.GetChars()) == 0) { - if (Bstrcasecmp(map_name, LevelInfo[j].LevelName) == 0) - { *level = j; return; } } - } *level = 0; return; @@ -1171,7 +1083,7 @@ InitLevel(void) // A few IMPORTANT GLOBAL RESETS InitLevelGlobals(); if (!DemoMode) - StopSong(); + Mus_Stop(); if (LoadGameOutsideMoveLoop) { @@ -1197,8 +1109,7 @@ InitLevel(void) FindLevelInfo(LevelName, &Level); if (Level > 0) { - strcpy(LevelSong, LevelInfo[Level].SongName); - strcpy(LevelName, LevelInfo[Level].LevelName); + strcpy(LevelName, mapList[Level].fileName); UserMapName[0] = '\0'; } else @@ -1236,15 +1147,13 @@ InitLevel(void) if (Level > 0) { // user map is part of game - treat it as such - strcpy(LevelSong, LevelInfo[Level].SongName); - strcpy(LevelName, LevelInfo[Level].LevelName); + strcpy(LevelName, mapList[Level].fileName); UserMapName[0] = '\0'; } } else { - strcpy(LevelName, LevelInfo[Level].LevelName); - strcpy(LevelSong, LevelInfo[Level].SongName); + strcpy(LevelName, mapList[Level].fileName); } } @@ -1258,7 +1167,12 @@ InitLevel(void) if (!DemoMode && !DemoInitOnce) DemoPlaySetup(); - LoadLevel(LevelName); + if (!LoadLevel(LevelName)) + { + NewGame = false; + return; + } + STAT_NewLevel(LevelName); if (Bstrcasecmp(CacheLastLevel, LevelName) != 0) // clears gotpic and does some bit setting @@ -1353,8 +1267,8 @@ InitLevel(void) if (ArgCheat) { - SWBOOL bak = hud_messages; - hud_messages = FALSE; + int bak = hud_messages; + hud_messages = 0; EveryCheatToggle(&Player[0],NULL); hud_messages = bak; GodMode = TRUE; @@ -1515,6 +1429,7 @@ void NewLevel(void) FX_SetVolume(0); // Shut the hell up while game is loading! InitLevel(); RunLevel(); + STAT_Update(false); if (!QuitFlag) { @@ -1539,6 +1454,7 @@ void NewLevel(void) { PlayTheme(); MenuLevel(); + STAT_Update(true); } } else @@ -1547,6 +1463,7 @@ void NewLevel(void) { PlayTheme(); MenuLevel(); + STAT_Update(true); } } FinishAnim = 0; @@ -1600,8 +1517,7 @@ void ResetKeyRange(uint8_t* kb, uint8_t* ke) void PlayTheme() { // start music at logo - strcpy(LevelSong,"theme.mid"); - PlaySong(LevelSong, RedBookSong[0], TRUE, TRUE); + PlaySong(nullptr, ThemeSongs[0], ThemeTrack[0]); DSPRINTF(ds,"After music stuff..."); MONO_PRINT(ds); @@ -1616,9 +1532,9 @@ void LogoLevel(void) MONO_PRINT(ds); // PreCache Anim - LoadAnm(0); + LoadAnm(0, &fin); - auto pal = kloadfile("3drealms.pal", 0); + auto pal = fileSystem.LoadFile("3drealms.pal", 0); if (pal.Size() >= 768) { @@ -1649,7 +1565,6 @@ void LogoLevel(void) while (TRUE) { handleevents(); - if (quitevent) { QuitFlag = TRUE; break; } // taken from top of faketimerhandler // limits checks to max of 40 times a second @@ -1694,7 +1609,6 @@ void CreditsLevel(void) // get rid of all PERM sprites! renderFlushPerms(); save = gs.BorderNum; - SetBorder(Player + myconnectindex,0); ClearStartMost(); gs.BorderNum = save; videoClearViewableArea(0L); @@ -1707,9 +1621,9 @@ void CreditsLevel(void) while (FX_SoundActive(handle)) ; // try 14 then 2 then quit - if (!PlaySong(NULL, 14, FALSE, TRUE)) + if (!PlaySong(nullptr, ThemeSongs[5], ThemeTrack[5], true)) { - if (!PlaySong(NULL, 2, FALSE, TRUE)) + if (!PlaySong(nullptr, nullptr, 2, true)) { handle = PlaySound(DIGI_NOLIKEMUSIC,&zero,&zero,&zero,v3df_none); if (handle > 0) @@ -1750,10 +1664,6 @@ void CreditsLevel(void) curpic = CREDITS1_PIC; } - - if (!SongIsPlaying()) - break; - if (inputState.GetKeyStatus(KEYSC_ESC)) break; } @@ -1762,7 +1672,7 @@ void CreditsLevel(void) videoClearViewableArea(0L); videoNextPage(); ResetKeys(); - StopSong(); + Mus_Stop(); } @@ -1777,7 +1687,7 @@ void SybexScreen(void) videoNextPage(); ResetKeys(); - while (!KeyPressed() && !quitevent) handleevents(); + while (!KeyPressed()) handleevents(); } // CTW REMOVED END @@ -1824,7 +1734,7 @@ TitleLevel(void) //MNU_CheckForMenusAnyKey(); } - //if (UsingMenus) + //if (M_Active()) // MNU_DrawMenu(); //drawscreen as fast as you can @@ -1888,10 +1798,8 @@ void MenuLevel(void) int fin; short w,h; - DSPRINTF(ds,"MenuLevel..."); - MONO_PRINT(ds); - - + M_StartControlPanel(false); + M_SetMenu(NAME_MainMenu); // do demos only if not playing multi play if (!CommEnabled && numplayers <= 1 && !FinishAnim && !NoDemoStartup) { @@ -1946,7 +1854,8 @@ void MenuLevel(void) if (FinishAnim) { inputState.ClearKeyStatus(sc_Escape); - ControlPanelType = ct_ordermenu; + M_StartControlPanel(false); + M_SetMenu(NAME_CreditsMenu); FinishAnim = 0; } } @@ -1960,14 +1869,11 @@ void MenuLevel(void) handleevents(); OSD_DispatchQueued(); - if (quitevent) QuitFlag = TRUE; - // taken from top of faketimerhandler // limits checks to max of 40 times a second if (totalclock >= ototalclock + synctics) { ototalclock += synctics; - MNU_CheckForMenusAnyKey(); if (CommEnabled) getpackets(); } @@ -2004,22 +1910,12 @@ void MenuLevel(void) break; } - // force the use of menus at all time - if (!UsingMenus && !ConPanel) - { - inputState.SetKeyStatus(sc_Escape); - MNU_CheckForMenusAnyKey(); - } - // must lock the clock for drawing so animations will happen totalclocklock = totalclock; //drawscreen as fast as you can DrawMenuLevelScreen(); - if (UsingMenus) - MNU_DrawMenu(); - videoNextPage(); } @@ -2027,8 +1923,7 @@ void MenuLevel(void) //LoadGameOutsideMoveLoop = FALSE; inputState.ClearKeyStatus(sc_Escape); inputState.ClearKeysDown(); - //ExitMenus(); - UsingMenus = FALSE; + M_ClearMenus(); InMenuLevel = FALSE; videoClearViewableArea(0L); videoNextPage(); @@ -2079,11 +1974,7 @@ void LoadingLevelScreen(char *level_name) MNU_MeasureString(ds, &w, &h); MNU_DrawString(TEXT_TEST_COL(w), 170, ds,1,16); - if (UserMapName[0]) - sprintf(ds,"%s",UserMapName); - else - sprintf(ds,"%s",LevelInfo[Level].Description); - + auto ds = currentLevel->DisplayName(); MNU_MeasureString(ds, &w, &h); MNU_DrawString(TEXT_TEST_COL(w), 180, ds,1,16); @@ -2141,13 +2032,15 @@ int BonusGrabSound(short SpriteNum) return 0; } +extern SWBOOL FinishedLevel; +extern int PlayClock; +extern short LevelSecrets; +extern short TotalKillable; + void BonusScreen(PLAYERp pp) { int minutes,seconds,second_tics; - extern SWBOOL FinishedLevel; - extern int PlayClock; - extern short LevelSecrets; - extern short TotalKillable; + short w,h; short pic,limit; int zero=0; @@ -2265,10 +2158,7 @@ void BonusScreen(PLAYERp pp) totalclock = ototalclock = 0; limit = synctics; - if (MusicEnabled()) - { - PlaySong(voc[DIGI_ENDLEV].name, 3, TRUE, TRUE); - } + PlaySong(nullptr, ThemeSongs[1], ThemeTrack[1]); // special case code because I don't care any more! if (FinishAnim) @@ -2277,7 +2167,7 @@ void BonusScreen(PLAYERp pp) rotatesprite(0, 0, RS_SCALE, 0, 5120, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); rotatesprite(158<<16, 86<<16, RS_SCALE, 0, State->Pic, 0, 0, TITLE_ROT_FLAGS, 0, 0, xdim - 1, ydim - 1); videoNextPage(); - FadeIn(0,0); + //FadeIn(0,0); } BonusDone = FALSE; @@ -2318,7 +2208,7 @@ void BonusScreen(PLAYERp pp) { if (PlayingLevel <= 1) PlayingLevel = 1; - sprintf(ds,"%s",LevelInfo[PlayingLevel].Description); + auto ds = currentLevel->DisplayName(); MNU_MeasureString(ds, &w, &h); MNU_DrawString(TEXT_TEST_COL(w), 20, ds,1,19); } @@ -2342,12 +2232,12 @@ void BonusScreen(PLAYERp pp) if (!UserMapName[0]) { line++; - sprintf(ds,"3D Realms Best Time: %s", LevelInfo[PlayingLevel].BestTime); + sprintf(ds,"3D Realms Best Time: %d:%02d", currentLevel->designerTime/60, currentLevel->designerTime%60); MNU_MeasureString(ds, &w, &h); MNU_DrawString(40, BONUS_LINE(line), ds,1,16); line++; - sprintf(ds,"Par Time: %s", LevelInfo[PlayingLevel].ParTime); + sprintf(ds,"Par Time: %d:%02d", currentLevel->parTime/ 60, currentLevel->parTime%60); MNU_MeasureString(ds, &w, &h); MNU_DrawString(40, BONUS_LINE(line), ds,1,16); } @@ -2370,7 +2260,6 @@ void BonusScreen(PLAYERp pp) MNU_DrawString(TEXT_TEST_COL(w), 185, ds,1,19); videoNextPage(); - ScreenCaptureKeys(); if (State == State->NextState) BonusDone = TRUE; @@ -2383,7 +2272,7 @@ void BonusScreen(PLAYERp pp) void EndGameSequence(void) { SWBOOL anim_ok = TRUE; - FadeOut(0, 5); + //FadeOut(0, 5); if ((adult_lockout || Global_PLock) && FinishAnim == ANIM_SUMO) anim_ok = FALSE; @@ -2450,7 +2339,7 @@ void StatScreen(PLAYERp mpp) // No stats in bot games //if (BotMode) return; - ResetPalette(mpp); + //ResetPalette(mpp); COVER_SetReverb(0); // Reset reverb StopSound(); @@ -2474,17 +2363,18 @@ void StatScreen(PLAYERp mpp) memset(death_total,0,sizeof(death_total)); memset(kills,0,sizeof(kills)); - sprintf(ds,"MULTIPLAYER TOTALS"); - MNU_MeasureString(ds, &w, &h); - MNU_DrawString(TEXT_TEST_COL(w), 68, ds, 0, 0); + auto c = GStrings("MULTIPLAYER TOTALS"); + MNU_MeasureString(c, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 68, c, 0, 0); - sprintf(ds,"PRESS SPACE BAR TO CONTINUE"); - MNU_MeasureString(ds, &w, &h); - MNU_DrawString(TEXT_TEST_COL(w), 189, ds, 0, 0); + c = GStrings("TXTS_PRESSSPACE"); + MNU_MeasureString(c, &w, &h); + MNU_DrawString(TEXT_TEST_COL(w), 189, c, 0, 0); x = STAT_START_X; y = STAT_START_Y; + // Hm.... how to translate this without messing up the formatting? sprintf(ds," NAME 1 2 3 4 5 6 7 8 KILLS"); DisplayMiniBarSmString(mpp, x, y, 0, ds); rows = OrigCommPlayers; @@ -2546,7 +2436,7 @@ void StatScreen(PLAYERp mpp) x = STAT_START_X; y += STAT_OFF_Y; - sprintf(ds," DEATHS"); + sprintf(ds," %s", GStrings("DEATHS")); DisplayMiniBarSmString(mpp, x, y, 0, ds); x = STAT_TABLE_X; @@ -2584,16 +2474,11 @@ void StatScreen(PLAYERp mpp) inputState.ClearKeyStatus(KEYSC_SPACE); inputState.ClearKeyStatus(KEYSC_ENTER); - if (MusicEnabled()) - { - PlaySong(voc[DIGI_ENDLEV].name, 3, TRUE, TRUE); - } + PlaySong(nullptr, ThemeSongs[1], ThemeTrack[1]); while (!inputState.GetKeyStatus(KEYSC_SPACE) && !inputState.GetKeyStatus(KEYSC_ENTER)) { handleevents(); - - ScreenCaptureKeys(); } StopSound(); @@ -2638,7 +2523,7 @@ void Control() InitGame(); MONO_PRINT("InitGame done"); - MNU_InitMenus(); + //MNU_InitMenus(); InGame = TRUE; GameIntro(); @@ -2647,8 +2532,6 @@ void Control() handleevents(); OSD_DispatchQueued(); - if (quitevent) QuitFlag = TRUE; - NewLevel(); } @@ -2756,9 +2639,6 @@ void MoveLoop(void) // demosync_record(); #endif } - - if (!InputMode && !PauseKeySet) - MNU_CheckForMenus(); } @@ -2789,8 +2669,6 @@ void InitPlayerGameSettings(void) else RESET(Player[myconnectindex].Flags, PF_AUTO_AIM); } - - g_MyAimMode = in_aimmode; } @@ -2809,7 +2687,6 @@ void InitRunLevel(void) if (snd_ambience) StartAmbientSound(); SetCrosshair(); - PlaySong(LevelSong, -1, TRUE, TRUE); SetRedrawScreen(Player + myconnectindex); // crappy little hack to prevent play clock from being overwritten // for load games @@ -2831,7 +2708,7 @@ void InitRunLevel(void) waitforeverybody(); - StopSong(); + Mus_Stop(); if (Bstrcasecmp(CacheLastLevel, LevelName) != 0) DoTheCache(); @@ -2846,16 +2723,14 @@ void InitRunLevel(void) InitNetVars(); { - int track; if (Level == 0) { - track = RedBookSong[4+RANDOM_RANGE(10)]; + PlaySong(nullptr, currentLevel->music, 1 + RANDOM_RANGE(10)); } else { - track = RedBookSong[Level]; + PlaySong(currentLevel->labelName, currentLevel->music, currentLevel->cdSongId); } - PlaySong(LevelSong, track, TRUE, TRUE); } InitPrediction(&Player[myconnectindex]); @@ -2891,7 +2766,6 @@ void RunLevel(void) InitRunLevel(); FX_SetVolume(snd_fxvolume); - SetSongVolume(mus_volume); #if 0 waitforeverybody(); @@ -2905,8 +2779,6 @@ void RunLevel(void) D_ProcessEvents(); faketimerhandler(); - if (quitevent) QuitFlag = TRUE; - MoveLoop(); @@ -3020,24 +2892,7 @@ char isShareware = FALSE; int DetectShareware(void) { -#define DOS_SCREEN_NAME_SW "SHADSW.BIN" -#define DOS_SCREEN_NAME_REG "SWREG.BIN" - - int h; - - if (testkopen(DOS_SCREEN_NAME_SW, 1)) - { - isShareware = TRUE; - return 0; - } - - if (testkopen(DOS_SCREEN_NAME_REG, 1)) - { - isShareware = FALSE; - return 0; - } - - return 1; // heavens knows what this is... + return (isShareware = !!(g_gameType & GAMEFLAG_SHAREWARE)); } @@ -3056,6 +2911,7 @@ int32_t GameInterface::app_main() int cnt = 0; uint32_t TotalMemory; + BorderAdjust = true; SW_ExtInit(); CONFIG_ReadSetup(); @@ -3071,13 +2927,6 @@ int32_t GameInterface::app_main() else buildputs("Detected registered GRP\n"); } - if (SW_SHAREWARE) - { - // Zero out the maps that aren't in shareware version - memset(&LevelInfo[MAX_LEVELS_SW+1], 0, sizeof(LEVEL_INFO)*(MAX_LEVELS_REG-MAX_LEVELS_SW)); - GameVersion++; - } - for (i = 0; i < MAX_SW_PLAYERS; i++) INITLIST(&Player[i].PanelSpriteList); @@ -3193,187 +3042,10 @@ void ManualPlayerDelete(PLAYERp cur_pp) } } -#if DEBUG -void SinglePlayInput(PLAYERp pp) -{ - int pnum = myconnectindex; - uint8_t* kp; - if (buttonMap.ButtonDown(gamefunc_See_Co_Op_View) && !UsingMenus && !ConPanel && dimensionmode == 3) - { - short oldscreenpeek = screenpeek; - - buttonMap.ClearButton(gamefunc_See_Co_Op_View); - - screenpeek = connectpoint2[screenpeek]; - - if (screenpeek < 0) - screenpeek = connecthead; - - if (dimensionmode == 2 || dimensionmode == 5 || dimensionmode == 6) - setup2dscreen(); - - if (dimensionmode != 2) - { - PLAYERp tp; - - tp = Player + screenpeek; - PlayerUpdatePanelInfo(tp); - setpalettefade(0,0,0,0); - memcpy(pp->temp_pal, palette_data, sizeof(palette_data)); - DoPlayerDivePalette(tp); - DoPlayerNightVisionPalette(tp); -// printf("SingPlayInput set_pal: tp->PlayerSprite = %d\n",tp->PlayerSprite); - } - } - - -} - -void DebugKeys(PLAYERp pp) -{ - short w, h; - - if (!(inputState.GetKeyStatus(KEYSC_ALT) || inputState.GetKeyStatus(KEYSC_RALT))) - return; - - if (InputMode) - return; - - if (CommEnabled) - return; - - // - // visiblity adjust - // - - if (inputState.GetKeyStatus(KEYSC_L) > 0) - { - if (inputState.GetKeyStatus(KEYSC_LSHIFT) | inputState.GetKeyStatus(KEYSC_RSHIFT)) // SHIFT - { - g_visibility = g_visibility - (g_visibility >> 3); - - if (g_visibility < 128) - g_visibility = 16348; - - //if (g_visibility > 16384) - // g_visibility = 128; - } - else - { - inputState.GetKeyStatus(KEYSC_L) = 0; - - g_visibility = g_visibility - (g_visibility >> 3); - - if (g_visibility > 16384) - g_visibility = 128; - } - } - - // - // parallax changes - // - - if (inputState.GetKeyStatus(KEYSC_X)) - { - if (inputState.GetKeyStatus(KEYSC_LSHIFT)) - { - inputState.GetKeyStatus(KEYSC_LSHIFT) = FALSE; - inputState.GetKeyStatus(KEYSC_X) = 0; - - parallaxyoffs_override += 10; - - if (parallaxyoffs_override > 100) - parallaxyoffs_override = 0; - } - else - { - inputState.GetKeyStatus(KEYSC_X) = 0; - parallaxtype++; - if (parallaxtype > 2) - parallaxtype = 0; - } - } -} - -#endif - -void ConKey(void) -{ -#if DEBUG - // Console Input Panel - if (!ConPanel && dimensionmode == 3) - { - //if (inputState.GetKeyStatus(KEYSC_TILDE) && inputState.GetKeyStatus(KEYSC_LSHIFT)) - if (inputState.GetKeyStatus(KEYSC_TILDE)) - { - inputState.GetKeyStatus(KEYSC_TILDE) = FALSE; - //inputState.GetKeyStatus(KEYSC_LSHIFT) = FALSE; - inputState.keyFlushChars(); - ConPanel = TRUE; - InputMode = TRUE; - ConInputMode = TRUE; - if (!CommEnabled) - GamePaused = TRUE; - memset(MessageInputString, '\0', sizeof(MessageInputString)); - } - } - else if (ConPanel) - { - //if (inputState.GetKeyStatus(KEYSC_TILDE) && inputState.GetKeyStatus(KEYSC_LSHIFT)) - if (inputState.GetKeyStatus(KEYSC_TILDE)) - { - inputState.GetKeyStatus(KEYSC_TILDE) = FALSE; - //inputState.GetKeyStatus(KEYSC_LSHIFT) = FALSE; - inputState.keyFlushChars(); - ConPanel = FALSE; - ConInputMode = FALSE; - InputMode = FALSE; - if (!CommEnabled) - GamePaused = FALSE; - memset(MessageInputString, '\0', sizeof(MessageInputString)); - SetFragBar(Player + myconnectindex); - } - } -#endif -} char WangBangMacro[10][64]; -SWBOOL DoQuickSave(short save_num) -{ - PauseAction(); - - if (SaveGame(save_num) != -1) - { - QuickLoadNum = save_num; - - LastSaveNum = -1; - - return FALSE; - } - - return TRUE; -} - -SWBOOL DoQuickLoad() -{ - //KB_ClearKeysDown(); - - PauseAction(); - - ReloadPrompt = FALSE; - if (LoadGame(QuickLoadNum) == -1) - { - return FALSE; - } - - ready2send = 1; - LastSaveNum = -1; - - return TRUE; -} - void FunctionKeys(PLAYERp pp) { @@ -3446,88 +3118,10 @@ FunctionKeys(PLAYERp pp) return; } - - if (numplayers <= 1) - { - // F2 save menu - if (inputState.GetKeyStatus(KEYSC_F2)) - { - inputState.ClearKeyStatus(KEYSC_F2); - if (!TEST(pp->Flags, PF_DEAD)) - { - inputState.SetKeyStatus(sc_Escape); - ControlPanelType = ct_savemenu; - } - } - - // F3 load menu - if (inputState.GetKeyStatus(KEYSC_F3)) - { - inputState.ClearKeyStatus(KEYSC_F3); - if (!TEST(pp->Flags, PF_DEAD)) - { - inputState.SetKeyStatus(sc_Escape); - ControlPanelType = ct_loadmenu; - } - } - - // F6 quick save - if (inputState.GetKeyStatus(KEYSC_F6)) - { - inputState.ClearKeyStatus(KEYSC_F6); - if (!TEST(pp->Flags, PF_DEAD)) - { - inputState.SetKeyStatus(sc_Escape); - if (QuickLoadNum < 0) - { - //KEY_PRESSED(KEYSC_ESC) = 1; - ControlPanelType = ct_savemenu; - } - else - { - //KB_ClearKeysDown(); - //KB_FlushKeyboardQueue(); - DoQuickSave(QuickLoadNum); - ResumeAction(); - } - } - } - - // F9 quick load - if (inputState.GetKeyStatus(KEYSC_F9)) - { - inputState.ClearKeyStatus(KEYSC_F9); - - if (!TEST(pp->Flags, PF_DEAD)) - { - if (QuickLoadNum < 0) - { - //KEY_PRESSED(KEYSC_ESC) = 1; - ControlPanelType = ct_loadmenu; - } - else - { - DoQuickLoad(); - ResumeAction(); - } - } - } - } - - - // F4 sound menu - if (inputState.GetKeyStatus(KEYSC_F4)) - { - inputState.ClearKeyStatus(KEYSC_F4); - inputState.SetKeyStatus(sc_Escape); - ControlPanelType = ct_soundmenu; - } - - // F7 VIEW control - if (inputState.GetKeyStatus(KEYSC_F7)) + if (buttonMap.ButtonDown(gamefunc_Third_Person_View)) { - inputState.ClearKeyStatus(KEYSC_F7); + buttonMap.ClearButton(gamefunc_Third_Person_View); if (inputState.GetKeyStatus(KEYSC_LSHIFT) || inputState.GetKeyStatus(KEYSC_RSHIFT)) { @@ -3548,33 +3142,6 @@ FunctionKeys(PLAYERp pp) } } - // F8 toggle messages - if (inputState.GetKeyStatus(KEYSC_F8)) - { - inputState.ClearKeyStatus(KEYSC_F8); - - hud_messages = !hud_messages; - - if (hud_messages) - PutStringInfoLine(pp, "Messages ON"); - else - PutStringInfoLine(pp, "Messages OFF"); - } - - // F10 quit menu - if (inputState.GetKeyStatus(KEYSC_F10)) - { - inputState.ClearKeyStatus(KEYSC_F10); - inputState.SetKeyStatus(sc_Escape); - ControlPanelType = ct_quitmenu; - } - - // F11 gamma correction - if (inputState.GetKeyStatus(KEYSC_F11) > 0) - { - inputState.ClearKeyStatus(KEYSC_F11); - // Do this entirely in the video backend. - } } @@ -3583,7 +3150,7 @@ void PauseKey(PLAYERp pp) extern SWBOOL GamePaused,CheatInputMode; extern SWBOOL enabled; - if (inputState.GetKeyStatus(sc_Pause) && !CommEnabled && !InputMode && !UsingMenus && !CheatInputMode && !ConPanel) + if (inputState.GetKeyStatus(sc_Pause) && !CommEnabled && !InputMode && !M_Active() && !CheatInputMode && !ConPanel) { inputState.ClearKeyStatus(sc_Pause); @@ -3600,12 +3167,12 @@ void PauseKey(PLAYERp pp) #define MSG_GAME_PAUSED "Game Paused" MNU_MeasureString(MSG_GAME_PAUSED, &w, &h); PutStringTimer(pp, TEXT_TEST_COL(w), 100, MSG_GAME_PAUSED, 999); - PauseSong(TRUE); + Mus_SetPaused(true); } else { pClearTextLine(pp, 100); - PauseSong(FALSE); + Mus_SetPaused(false); } } @@ -3613,15 +3180,15 @@ void PauseKey(PLAYERp pp) { if (ReloadPrompt) { - if (QuickLoadNum < 0) - { ReloadPrompt = FALSE; + /* } else { inputState.SetKeyStatus(sc_Escape); ControlPanelType = ct_quickloadmenu; } + */ } } } @@ -3655,6 +3222,7 @@ void GetMessageInput(PLAYERp pp) } } } +#if 0 // the message input needs to be moved out of the game code! else if (MessageInputMode && !ConInputMode) { if (gs.BorderNum > BORDER_BAR+1) @@ -3776,141 +3344,7 @@ SEND_MESSAGE: break; } } -} - -void GetConInput(PLAYERp pp) -{ - int pnum = myconnectindex; - short w,h; - static SWBOOL cur_show; - - if (MessageInputMode || HelpInputMode) - return; - - ConKey(); - - // Console input commands - if (ConInputMode && !MessageInputMode) - { - // get input - switch (MNU_InputSmallString(MessageInputString, 250)) - { - case -1: // Cancel Input (pressed ESC) or Err - InputMode = FALSE; - inputState.ClearKeysDown(); - inputState.keyFlushChars(); - memset(MessageInputString, '\0', sizeof(MessageInputString)); - break; - case FALSE: // Input finished (RETURN) - if (MessageInputString[0] == '\0') - { - InputMode = FALSE; - inputState.ClearKeysDown(); - inputState.keyFlushChars(); - buttonMap.ClearButton(gamefunc_Inventory); - memset(MessageInputString, '\0', sizeof(MessageInputString)); - } - else - { - InputMode = FALSE; - inputState.ClearKeysDown(); - inputState.keyFlushChars(); - buttonMap.ClearButton(gamefunc_Inventory); - CON_ConMessage("%s", MessageInputString); - CON_ProcessUserCommand(); // Check to see if it's a cheat or command - - conbot += 6; - conbotgoal = conbot; - //addconquote(MessageInputString); - // Clear it out after every entry - memset(MessageInputString, '\0', sizeof(MessageInputString)); - } - break; - case TRUE: // Got input - break; - } - } -} - - -void GetHelpInput(PLAYERp pp) -{ - extern SWBOOL GamePaused; - - if (inputState.GetKeyStatus(KEYSC_ALT) || inputState.GetKeyStatus(KEYSC_RALT)) - return; - - if (inputState.GetKeyStatus(KEYSC_LSHIFT) || inputState.GetKeyStatus(KEYSC_RSHIFT)) - return; - - if (MessageInputMode || ConInputMode) - return; - - // F1 help menu - if (!HelpInputMode) - { - if (inputState.GetKeyStatus(KEYSC_F1)) - { - inputState.ClearKeyStatus(KEYSC_F11); - HelpPage = 0; - HelpInputMode = TRUE; - PanelUpdateMode = FALSE; - InputMode = TRUE; - if (!CommEnabled) - GamePaused = TRUE; - } - } - else if (HelpInputMode) - { - if (inputState.GetKeyStatus(KEYSC_ESC)) - { - inputState.ClearKeyStatus(sc_Escape); - inputState.ClearKeysDown(); - PanelUpdateMode = TRUE; - HelpInputMode = FALSE; - InputMode = FALSE; - if (!CommEnabled) - GamePaused = FALSE; - SetRedrawScreen(pp); - } - - if (inputState.GetKeyStatus(KEYSC_SPACE) || inputState.GetKeyStatus(KEYSC_ENTER) || inputState.GetKeyStatus(KEYSC_PGDN) || inputState.GetKeyStatus(KEYSC_DOWN) || inputState.GetKeyStatus(KEYSC_RIGHT) || inputState.GetKeyStatus(sc_kpad_3) || inputState.GetKeyStatus(sc_kpad_2) || inputState.GetKeyStatus(sc_kpad_6)) - { - inputState.ClearKeyStatus(KEYSC_SPACE); - inputState.ClearKeyStatus(KEYSC_ENTER); - inputState.ClearKeyStatus(KEYSC_PGDN); - inputState.ClearKeyStatus(KEYSC_DOWN); - inputState.ClearKeyStatus(KEYSC_RIGHT); - inputState.ClearKeyStatus(sc_kpad_3); - inputState.ClearKeyStatus(sc_kpad_2); - inputState.ClearKeyStatus(sc_kpad_6); - - HelpPage++; - if (HelpPage >= (int)SIZ(HelpPagePic)) - // CTW MODIFICATION - // "Oops! I did it again..." - // HelpPage = SIZ(HelpPagePic) - 1; - HelpPage = 0; - // CTW MODIFICATION END - } - - if (inputState.GetKeyStatus(KEYSC_PGUP) || inputState.GetKeyStatus(KEYSC_UP) || inputState.GetKeyStatus(KEYSC_LEFT) || inputState.GetKeyStatus(sc_kpad_9) || inputState.GetKeyStatus(sc_kpad_8) || inputState.GetKeyStatus(sc_kpad_4)) - { - inputState.ClearKeyStatus(KEYSC_PGUP); - inputState.ClearKeyStatus(KEYSC_UP); - inputState.ClearKeyStatus(KEYSC_LEFT); - inputState.ClearKeyStatus(sc_kpad_8); - inputState.ClearKeyStatus(sc_kpad_9); - inputState.ClearKeyStatus(sc_kpad_4); - - HelpPage--; - if (HelpPage < 0) - // CTW MODIFICATION - // "Played with the logic, got lost in the game..." - HelpPage = SIZ(HelpPagePic) - 1; - // CTW MODIFICATION END - } - } +#endif } short MirrorDelay; @@ -3952,54 +3386,27 @@ void getinput(SW_PACKET *loc) // MAKE SURE THIS WILL GET SET SET_LOC_KEY(loc->bits, SK_QUIT_GAME, MultiPlayQuitFlag); - if (in_aimmode) - g_MyAimMode = 0; + bool mouseaim = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); - if (buttonMap.ButtonDown(gamefunc_Mouse_Aiming)) + if (!CommEnabled) { - if (in_aimmode) - g_MyAimMode = 1; - else - { - buttonMap.ClearButton(gamefunc_Mouse_Aiming); - g_MyAimMode = !g_MyAimMode; - if (g_MyAimMode) - { - PutStringInfo(pp, "Mouse Aiming Off"); - } - else - { - PutStringInfo(pp, "Mouse Aiming On"); - } - } - } + // Go back to the source to set this - the old code here was catastrophically bad. + // this needs to be fixed properly - as it is this can never be compatible with demo playback. - int const aimMode = TEST(pp->Flags, PF_MOUSE_AIMING_ON); + if (mouseaim) + SET(Player[myconnectindex].Flags, PF_MOUSE_AIMING_ON); + else + RESET(Player[myconnectindex].Flags, PF_MOUSE_AIMING_ON); + + if (cl_autoaim) + SET(Player[myconnectindex].Flags, PF_AUTO_AIM); + else + RESET(Player[myconnectindex].Flags, PF_AUTO_AIM); + } ControlInfo info; CONTROL_GetInput(&info); - if (in_mousedeadzone) - { - if (info.mousey > 0) - info.mousey = max(info.mousey - in_mousedeadzone, 0); - else if (info.mousey < 0) - info.mousey = min(info.mousey + in_mousedeadzone, 0); - - if (info.mousex > 0) - info.mousex = max(info.mousex - in_mousedeadzone, 0); - else if (info.mousex < 0) - info.mousex = min(info.mousex + in_mousedeadzone, 0); - } - - if (in_mousebias) - { - if (klabs(info.mousex) > klabs(info.mousey)) - info.mousey = tabledivide32_noinline(info.mousey, in_mousebias); - else - info.mousex = tabledivide32_noinline(info.mousex, in_mousebias); - } - //info.dz = (info.dz * move_scale)>>8; //info.dyaw = (info.dyaw * turn_scale)>>8; @@ -4009,11 +3416,9 @@ void getinput(SW_PACKET *loc) if (PauseKeySet) return; - if (!MenuInputMode && !UsingMenus) + if (!M_Active()) { GetMessageInput(pp); - GetConInput(pp); - GetHelpInput(pp); } // MAP KEY @@ -4057,8 +3462,8 @@ void getinput(SW_PACKET *loc) if (ScrollMode2D && pp == Player + myconnectindex && !Prediction) MoveScrollMode2D(Player + myconnectindex); - // !JIM! Added UsingMenus so that you don't move at all while using menus - if (MenuInputMode || UsingMenus || ScrollMode2D || InputMode) + // !JIM! Added M_Active() so that you don't move at all while using menus + if (M_Active() || ScrollMode2D || InputMode) return; SET_LOC_KEY(loc->bits, SK_SPACE_BAR, ((!!inputState.GetKeyStatus(KEYSC_SPACE)) | buttonMap.ButtonDown(gamefunc_Open))); @@ -4103,7 +3508,7 @@ void getinput(SW_PACKET *loc) angvel += info.dyaw * (turnamount << 1) / analogExtent; } - if (true)//aimMode) + if (mouseaim) aimvel = -info.mousey / 64; else vel = -(info.mousey >> 6); @@ -4186,12 +3591,15 @@ void getinput(SW_PACKET *loc) if (!CommEnabled) { + // What a mess...:? +#if 0 if (MenuButtonAutoAim) { MenuButtonAutoAim = FALSE; if ((!!TEST(pp->Flags, PF_AUTO_AIM)) != !!cl_autoaim) SET_LOC_KEY(loc->bits, SK_AUTO_AIM, TRUE); } +#endif } else if (inputState.GetKeyStatus(sc_Pause)) { @@ -4212,7 +3620,6 @@ void getinput(SW_PACKET *loc) SET_LOC_KEY(loc->bits, SK_LOOK_UP, buttonMap.ButtonDown(gamefunc_Look_Up)); SET_LOC_KEY(loc->bits, SK_LOOK_DOWN, buttonMap.ButtonDown(gamefunc_Look_Down)); - for (i = 0; i < MAX_WEAPONS_KEYS; i++) { if (buttonMap.ButtonDown(gamefunc_Weapon_1 + i)) @@ -4299,14 +3706,13 @@ void getinput(SW_PACKET *loc) SET(loc->bits, prev_weapon + 1); } - /* - if (buttonMap.ButtonDown(gamefunc_Alt_Weapon_Mode)) + if (buttonMap.ButtonDown(gamefunc_Alt_Weapon)) { - buttonMap.ClearButton(gamefunc_Alt_Weapon_Mode); + buttonMap.ClearButton(gamefunc_Alt_Weapon); USERp u = User[pp->PlayerSprite]; short const which_weapon = u->WeaponNum + 1; SET(loc->bits, which_weapon); - }*/ + inv_hotkey = 0; if (buttonMap.ButtonDown(gamefunc_Med_Kit)) @@ -4428,10 +3834,7 @@ void drawoverheadmap(int cposx, int cposy, int czoom, short cang) minigametext(txt_x,txt_y-7,"Follow Mode",0,2+8); } - if (UserMapName[0]) - sprintf(ds,"%s",UserMapName); - else - sprintf(ds,"%s",LevelInfo[Level].Description); + sprintf(ds,"%s",currentLevel->DisplayName()); minigametext(txt_x,txt_y,ds,0,2+8); @@ -4837,15 +4240,19 @@ void Saveable_Init_Dynamic() saveable_build.numdata = NUM_SAVEABLE_ITEMS(saveable_build_data); } -/*extern*/ bool GameInterface::validate_hud(int requested_size) { return requested_size; } -/*extern*/ void GameInterface::set_hud_layout(int requested_size) { /* the relevant setting is gs.BorderNum */} -/*extern*/ void GameInterface::set_hud_scale(int requested_size) { /* the relevant setting is gs.BorderNum */ } - -bool GameInterface::mouseInactiveConditional(bool condition) -{ - return condition; +/*extern*/ bool GameInterface::validate_hud(int requested_size) +{ + return requested_size != 10 && requested_size != 8; } - +/*extern*/ void GameInterface::set_hud_layout(int requested_size) +{ + if (requested_size >= 11) requested_size = 9; + else if (requested_size >= 9) requested_size = 8; + gs.BorderNum = 9 - requested_size; + SetBorder(Player + myconnectindex, gs.BorderNum); + SetRedrawScreen(Player + myconnectindex); +} +/*extern*/ void GameInterface::set_hud_scale(int requested_size) { /* the relevant setting is gs.BorderNum */ } ::GameInterface* CreateInterface() { @@ -4853,4 +4260,12 @@ bool GameInterface::mouseInactiveConditional(bool condition) } +GameStats GameInterface::getStats() +{ + PLAYERp pp = Player + myconnectindex; + return { pp->Kills, TotalKillable, pp->SecretsFound, LevelSecrets, PlayClock / 120, 0 }; +} + + + END_SW_NS diff --git a/source/sw/src/game.h b/source/sw/src/game.h index da5d2ad94..e27bffb0d 100644 --- a/source/sw/src/game.h +++ b/source/sw/src/game.h @@ -60,46 +60,43 @@ extern char isShareware; #define ERR_STD_ARG __FILE__, __LINE__ +void _Assert(const char *expr, const char *strFile, unsigned uLine); +#define PRODUCTION_ASSERT(f) \ + do { \ + if (!(f)) \ + _Assert(#f,ERR_STD_ARG); \ + } while (0) + +#if DEBUG || defined DEBUGGINGAIDS +#define ASSERT(f) PRODUCTION_ASSERT(f) +#else +#define ASSERT(f) do { } while (0) +#endif + #if DEBUG void HeapCheck(char *, int); #define HEAP_CHECK() HeapCheck(__FILE__, __LINE__) -void _Assert(const char *expr, const char *strFile, unsigned uLine); -#define ASSERT(f) \ - if (f) \ - do { } while(0); \ - else \ - _Assert(#f,ERR_STD_ARG); - -#define PRODUCTION_ASSERT(f) ASSERT(f) - void dsprintf(char *, char *, ...); #define DSPRINTF dsprintf void PokeStringMono(uint8_t Attr, uint8_t* String); -#if 1 // !JIM! Frank, I redirect this for me you'll want to set this back for you +#if 1 +// !JIM! Frank, I redirect this for me you'll want to set this back for you extern int DispMono; #define MONO_PRINT(str) if (DispMono) PokeStringMono(/*MDA_NORMAL*/ 0, str) #else void adduserquote(const char *daquote); extern int DispMono; -#define MONO_PRINT(str) if (DispMono) CON_ConMessage(str); // Put it in my userquote stuff! +#define MONO_PRINT(str) if (DispMono) OSD_Printf(str); // Put it in my userquote stuff! //#define MONO_PRINT(str) if (DispMono) printf(str); #endif #define RANDOM_DEBUG 1 // Set this to 1 for network testing. #else -#define ASSERT(f) do { } while(0) #define MONO_PRINT(str) -void _Assert(const char *expr, const char *strFile, unsigned uLine); -#define PRODUCTION_ASSERT(f) \ - if (f) \ - do { } while(0); \ - else \ - _Assert(#f,ERR_STD_ARG); - void dsprintf_null(char *str, const char *format, ...); #define DSPRINTF dsprintf_null //#define DSPRINTF() @@ -378,8 +375,8 @@ extern char MessageOutputString[256]; #define TEST_SYNC_KEY(player, sync_num) TEST((player)->input.bits, (1 << (sync_num))) #define RESET_SYNC_KEY(player, sync_num) RESET((player)->input.bits, (1 << (sync_num))) -#define TRAVERSE_SPRITE_SECT(l, o, n) for ((o) = (l); (n) = nextspritesect[o], (o) != -1; (o) = (n)) -#define TRAVERSE_SPRITE_STAT(l, o, n) for ((o) = (l); (n) = nextspritestat[o], (o) != -1; (o) = (n)) +#define TRAVERSE_SPRITE_SECT(l, o, n) for ((o) = (l); (n) = (o) == -1 ? -1 : nextspritesect[o], (o) != -1; (o) = (n)) +#define TRAVERSE_SPRITE_STAT(l, o, n) for ((o) = (l); (n) = (o) == -1 ? -1 : nextspritestat[o], (o) != -1; (o) = (n)) #define TRAVERSE_CONNECT(i) for (i = connecthead; i != -1; i = connectpoint2[i]) @@ -531,11 +528,11 @@ int StdRandomRange(int range); #define MDA_REVERSEBLINK 0xF0 // defines for move_sprite return value -#define HIT_MASK (BIT(13)|BIT(14)|BIT(15)) +#define HIT_MASK (BIT(14)|BIT(15)|BIT(16)) #define HIT_SPRITE (BIT(14)|BIT(15)) #define HIT_WALL BIT(15) #define HIT_SECTOR BIT(14) -#define HIT_PLAX_WALL BIT(13) +#define HIT_PLAX_WALL BIT(16) #define NORM_SPRITE(val) ((val) & (MAXSPRITES - 1)) #define NORM_WALL(val) ((val) & (MAXWALLS - 1)) @@ -857,8 +854,6 @@ void addconquote(const char *daquote); // Console // /////////////////////////////////////////////////////////////////////////////////////////// -void CON_Message(const char *message, ...) PRINTF_FORMAT(1, 2); -void CON_ConMessage(const char *message, ...) PRINTF_FORMAT(1, 2); void CON_StoreArg(const char *userarg); SWBOOL CON_CheckParm(const char *userarg); void CON_CommandHistory(signed char dir); @@ -891,8 +886,6 @@ typedef struct int16_t max_ammo; int16_t min_ammo; int16_t with_weapon; - const char *weapon_name; - const char *ammo_name; int16_t weapon_pickup; int16_t ammo_pickup; } DAMAGE_DATA, *DAMAGE_DATAp; @@ -949,34 +942,55 @@ typedef struct #define MAX_LEVELS_SW 4 #define MAX_LEVELS (isShareware ? MAX_LEVELS_SW : MAX_LEVELS_REG) -typedef struct -{ - const char *LevelName; - const char *SongName; - const char *Description; - const char *BestTime; - const char *ParTime; -} LEVEL_INFO, *LEVEL_INFOp, * *LEVEL_INFOpp; - -extern LEVEL_INFO LevelInfo[MAX_LEVELS_REG+2]; extern int ThemeTrack[6]; // w -extern const char *ThemeSongs[6]; // +extern FString ThemeSongs[6]; // #define MAX_EPISODE_NAME_LEN 24 extern char EpisodeNames[3][MAX_EPISODE_NAME_LEN+2]; -#define MAX_EPISODE_SUBTITLE_LEN 40 -extern char EpisodeSubtitles[3][MAX_EPISODE_SUBTITLE_LEN+1]; -#define MAX_SKILL_NAME_LEN 24 -extern char SkillNames[4][MAX_SKILL_NAME_LEN+2]; -#define MAX_FORTUNES 16 -extern const char *ReadFortune[MAX_FORTUNES]; -#define MAX_KEYS 8 -extern const char *KeyMsg[MAX_KEYS]; -extern const char *KeyDoorMessage[MAX_KEYS]; +enum +{ + MAX_KEYS = 8, + MAX_FORTUNES = 16, + MAX_INVENTORY_Q = 11,//InvDecl_TOTAL + + QUOTE_KEYMSG = 1, + QUOTE_DOORMSG = QUOTE_KEYMSG + MAX_KEYS, + // 23+24 are reserved. + QUOTE_COOKIE = 25, + QUOTE_INVENTORY = QUOTE_COOKIE + MAX_FORTUNES, + QUOTE_WPNFIST = QUOTE_INVENTORY + MAX_INVENTORY_Q, + QUOTE_WPNSWORD, + QUOTE_WPNSHURIKEN, + QUOTE_WPNSTICKY, + QUOTE_WPNUZI, + QUOTE_WPNLAUNCH, + QUOTE_WPNNUKE, + QUOTE_WPNGRENADE, + QUOTE_WPNRAILGUN, + QUOTE_WPNRIOT, + QUOTE_WPNHEAD, + QUOTE_WPNRIPPER, + // Here a gap of two needs to be inserted because the weapon array contains two bogus entries the parser can access. + // Not all ammo types here are used, but the entries must be reserved for the parser. + QUOTE_AMMOFIST = QUOTE_WPNRIPPER + 2, + QUOTE_AMMOSWORD, + QUOTE_AMMOSHURIKEN, + QUOTE_AMMOSTICKY, + QUOTE_AMMOUZI, + QUOTE_AMMOLAUNCH, + QUOTE_AMMONUKE, + QUOTE_AMMOGRENADE, + QUOTE_AMMORAILGUN, + QUOTE_AMMORIOT, + QUOTE_AMMOHEAD, + QUOTE_AMMORIPPER, + // Again, here a gap of two needs to be inserted because the weapon array contains two bogus entries the parser can access. + +}; typedef struct { @@ -1164,7 +1178,7 @@ struct PLAYERstruct short DiveDamageTics; // Death stuff - short DeathType; + uint16_t DeathType; short Kills; short Killer; //who killed me short KilledPlayer[MAX_SW_PLAYERS_REG]; @@ -2373,10 +2387,7 @@ int COVERinsertsprite(short sectnum, short statnum); //returns (short)spritenu void AudioUpdate(void); // stupid extern short LastSaveNum; -extern short QuickLoadNum; void LoadSaveMsg(const char *msg); -SWBOOL DoQuickSave(short save_num); -SWBOOL DoQuickLoad(void); struct GameInterface : ::GameInterface { @@ -2384,7 +2395,21 @@ struct GameInterface : ::GameInterface bool validate_hud(int) override; void set_hud_layout(int size) override; void set_hud_scale(int size) override; - bool mouseInactiveConditional(bool condition) override; + void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override; + void MenuOpened() override; + void MenuSound(EMenuSounds snd) override; + void MenuClosed() override; + bool CanSave() override; + void StartGame(FGameStartup& gs) override; + FSavegameInfo GetSaveSig() override; + void DrawMenuCaption(const DVector2& origin, const char* text) override; + void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) override; + bool LoadGame(FSaveGameNode* sv) override; + bool SaveGame(FSaveGameNode* sv) override; + void DoPrintMessage(int prio, const char* text) override; + void SetAmbience(bool on) override { if (on) StartAmbientSound(); else StopAmbientSound(); } + + GameStats getStats() override; }; diff --git a/source/sw/src/inv.cpp b/source/sw/src/inv.cpp index 157d51174..5e1fc31f6 100644 --- a/source/sw/src/inv.cpp +++ b/source/sw/src/inv.cpp @@ -138,7 +138,8 @@ void UpdateMiniBar(PLAYERp pp) rotatesprite(x << 16, y << 16, (1 << 16), 0, MINI_BAR_HEALTH_BOX_PIC, 0, 0, - ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER | RS_ALIGN_L, + 0, 0, xdim - 1, ydim - 1); x = MINI_BAR_HEALTH_BOX_X+3; DisplayMiniBarNumber(pp, x, y+5, u->Health); @@ -149,7 +150,8 @@ void UpdateMiniBar(PLAYERp pp) rotatesprite(x << 16, y << 16, (1 << 16), 0, MINI_BAR_AMMO_BOX_PIC, 0, 0, - ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER | RS_ALIGN_L, + 0, 0, xdim - 1, ydim - 1); x = MINI_BAR_AMMO_BOX_X+3; DisplayMiniBarNumber(pp, x, y+5, pp->WpnAmmo[u->WeaponNum]); @@ -163,7 +165,8 @@ void UpdateMiniBar(PLAYERp pp) rotatesprite(x << 16, y << 16, (1 << 16), 0, MINI_BAR_INVENTORY_BOX_PIC, 0, 0, - ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER | RS_ALIGN_L, + 0, 0, xdim - 1, ydim - 1); id = &InventoryData[pp->InventoryNum]; @@ -173,7 +176,8 @@ void UpdateMiniBar(PLAYERp pp) rotatesprite(x << 16, y << 16, (1 << 16), 0, id->State->picndx, 0, 0, - ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER | RS_ALIGN_L, + 0, 0, xdim - 1, ydim - 1); // will update the AUTO and % inventory values PlayerUpdateInventory(pp, pp->InventoryNum); diff --git a/source/sw/src/jweapon.cpp b/source/sw/src/jweapon.cpp index 58aa92bc9..823169808 100644 --- a/source/sw/src/jweapon.cpp +++ b/source/sw/src/jweapon.cpp @@ -1389,6 +1389,9 @@ PlayerInitChemBomb(PLAYERp pp) PlaySound(DIGI_THROW, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan | v3df_doppler); + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; nz = pp->posz + pp->bob_z + Z(8); @@ -1834,6 +1837,9 @@ PlayerInitCaltrops(PLAYERp pp) PlaySound(DIGI_THROW, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan | v3df_doppler); + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; nz = pp->posz + pp->bob_z + Z(8); diff --git a/source/sw/src/menus.cpp b/source/sw/src/menus.cpp index 7c0dae932..fef2dc1d8 100644 --- a/source/sw/src/menus.cpp +++ b/source/sw/src/menus.cpp @@ -53,1535 +53,22 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "fx_man.h" #include "music.h" #include "text.h" +#include "version.h" +#include "network.h" #include "colormap.h" #include "config.h" BEGIN_SW_NS -signed char MNU_InputString(char*, short); //#define PLOCK_VERSION TRUE +extern SWBOOL ExitLevel, NewGame; + short TimeLimitTable[9] = {0,3,5,10,15,20,30,45,60}; -short QuickLoadNum = -1; -char QuickLoadDescrDialog[128]; -SWBOOL SavePrompt = FALSE; -extern SWBOOL InMenuLevel, LoadGameOutsideMoveLoop, LoadGameFromDemo; -extern uint8_t RedBookSong[40]; -extern SWBOOL ExitLevel, NewGame; -extern short Level, Skill; -extern SWBOOL MusicInitialized, FxInitialized; -SWBOOL MNU_CheckUserMap(MenuItem *item); -SWBOOL MNU_SaveGameCheck(MenuItem_p item); -SWBOOL MNU_TeamPlayCheck(MenuItem *item); -SWBOOL MNU_CoopPlayCheck(MenuItem *item); -SWBOOL MNU_StatCheck(MenuItem *item); -SWBOOL MNU_LoadGameCheck(MenuItem *item); -SWBOOL MNU_TenCheck(MenuItem *item); -static SWBOOL MNU_TryMusicInit(void); -static void MNU_UpLevel(void); - -SWBOOL MNU_LoadSaveDraw(UserCall call, MenuItem *item); -SWBOOL MNU_LoadSaveMove(UserCall call, MenuItem *item); - -SWBOOL MenuButtonAutoRun = FALSE; -SWBOOL MenuButtonAutoAim = FALSE; -// misc load-save vars -short LastSaveNum = 99; -char SaveGameDescr[10][80]; -char BackupSaveGameDescr[80]; -short screen_tile = -1; - -SWBOOL MenuInputMode = FALSE; -int16_t MenuTextShade = 0; -SWBOOL passwordvalid = FALSE; - -SWBOOL MNU_HurtTeammateCheck(MenuItem *item); -SWBOOL MNU_TeamPlayChange(void); - -// Font pic table -unsigned short xlatfont[] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32 - 2274, 2294, 2274, 2277, 2278, 2280, 2295, 2282, 2283, 2281, 2286, 2297, 2285, // 45 - 2299, 2301, 2271, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, // 57 - 2292, 2293, 2296, 2287, 2298, 2300, 2275, 2236, 2237, 2238, 2239, 2240, // 69 - 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, // 81 - 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2290, 2289, 2291, // 93 - 2279, 2284, 2295, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, // 105 - 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, // 117 - 2257, 2258, 2259, 2260, 2261, 2282, 2288, 2283, 2272 // 126 -}; - -int slidersettings [sldr_max] = -{ - 0, SENSE_DEFAULT, FXVOL_DEFAULT, MUSIC_DEFAULT, SCRSIZE_DEFAULT, - BRIGHTNESS_DEFAULT, BORDERTILE_DEFAULT, GAMETYPE_DEFAULT, NETLEVEL_DEFAULT, - MONSTERS_DEFAULT, KILLLIMIT_DEFAULT, TIMELIMIT_DEFAULT, PLAYERCOLOR_DEFAULT, - 0,0, // video mode - 32767>>12, 32767>>12, // advanced mouse scale -}; - -short buttonsettings[btn_max]; - -// EXTERNS //////////////////////////// -#define XDIM 320 -#define YDIM 200 -extern SWBOOL QuitFlag; - -void TerminateGame(void); -void ResetKeys(void); - -// GLOBALS //////////////////////////// - -char playertextbuffer[80]; // Used for various input strings -char playerbuflen = 0; // Current length of the string in -// the buffer -char maxtextlen; // max length allowed for current - -static struct { int xdim,ydim; } validresolutions[MAXVALIDMODES]; -static int numvalidresolutions = 0, validbpps[8], numvalidbpps = 0; - -static void UpdateValidModes(int bpp, int fs) -{ - int i, j; - - numvalidresolutions = numvalidbpps = 0; - for (i=0; i 0) - { - inputState.ClearKeyStatus(inputState.GetLastScanCode()); - - - currentmode = 0; - } - - MNU_MeasureString(strs[0], &w, &h); - - y = (YDIM - (h+3) * SIZ(strs)) / 2; - - for (i=0; i<(int)SIZ(strs); i++) - { - w = 0; - auto c = buttonMap.GetButtonName(currentkey); - sprintf(ds,strs[i],c,col[currentcol]); - for (j=0; ds[j]; j++) if (ds[j] == '_') ds[j] = ' '; - MNU_MeasureString(ds, &w, &h); - MNU_DrawString((XDIM - w)/2, y, ds, 0, 16); - y += h+3; - } - - } - else - { - // key list -#define PGSIZ 14 - int topitem = 0, botitem = NUMGAMEFUNCTIONS; - int i,j; - const char *morestr = "More..."; - const char *p; - - if (inputState.GetKeyStatus(KEYSC_ESC)) - { - inputState.ClearKeyStatus(sc_Escape); - cust_callback = NULL; - return TRUE; - } - else if (inputState.GetKeyStatus(sc_Delete)) - { - inputState.ClearKeyStatus(sc_Delete); - //Bindings.UnbindACommand(buttonMap.GetButtonName(M_KEYBOARDKEYS.currentEntry)); - } - else if (inputState.GetKeyStatus(sc_Home)) - { - currentkey = 0; - inputState.ClearKeyStatus(sc_Home); - } - else if (inputState.GetKeyStatus(sc_End)) - { - currentkey = NUMGAMEFUNCTIONS-1; - inputState.ClearKeyStatus(sc_End); - } - else if (inputState.GetKeyStatus(sc_PgDn)) - { - currentkey += PGSIZ; - if (currentkey >= NUMGAMEFUNCTIONS) currentkey = NUMGAMEFUNCTIONS-1; - inputState.ClearKeyStatus(sc_PgDn); - } - else if (inputState.GetKeyStatus(sc_PgUp)) - { - currentkey -= PGSIZ; - if (currentkey < 0) currentkey = 0; - inputState.ClearKeyStatus(sc_PgUp); - } - else if (I_EscapeTrigger()) - { - currentmode = 1; - inputState.ClearLastScanCode(); - inputState.ClearKeysDown(); - } - else if (I_MenuUp()) - { - I_MenuUpClear(); - currentkey = max(0, currentkey - 1); - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - currentkey = min(NUMGAMEFUNCTIONS - 1, currentkey + 1); - } - else if (I_MenuRight()) - { - I_MenuRightClear(); - currentcol = 1; - } - else if (I_MenuLeft()) - { - I_MenuLeftClear(); - currentcol = 0; - } - - - if (NUMGAMEFUNCTIONS > PGSIZ) - { - topitem = currentkey - PGSIZ/2; - botitem = topitem + PGSIZ; - - if (topitem < 0) - { - botitem += -topitem; - topitem = 0; - } - else if (botitem >= NUMGAMEFUNCTIONS) - { - botitem = NUMGAMEFUNCTIONS-1; - topitem = botitem - PGSIZ; - } - } - - for (i = topitem; i <= botitem; i++) - { - auto c = buttonMap.GetButtonName(i); - for (j = 0; c[j]; j++) - { - if (c[j] == '_') ds[j] = ' '; - else ds[j] = c[j]; - } - ds[j] = 0; - -#if 0 - j = OPT_LINE(0)+(i-topitem)*8; - MNU_DrawSmallString(OPT_XS, j, ds, (i==currentkey) ? 0 : 12, 16); - - p = keyGetName(KeyboardKeys[i][0]); - if (!p || !KeyboardKeys[i][0] || KeyboardKeys[i][0]==0xff) p = " -"; - MNU_DrawSmallString(OPT_XSIDE, j, p, (i==currentkey) ? -5 : 12, - (i==currentkey && currentcol==0) ? 14 : 16); - - p = keyGetName(KeyboardKeys[i][1]); - if (!p || !KeyboardKeys[i][1] || KeyboardKeys[i][1]==0xff) p = " -"; - MNU_DrawSmallString(OPT_XSIDE + 4*14, j, p, (i==currentkey) ? -5 : 12, - (i==currentkey && currentcol==1) ? 14 : 16); -#endif - } - - { - short dx,dy; - dx = 0, dy = 8; - MNU_MeasureSmallString(morestr,&dx,&dy); - if (topitem > 0) - MNU_DrawSmallString(XDIM - OPT_XS - dx, OPT_LINE(0), morestr, 8,16); - if (botitem < NUMGAMEFUNCTIONS-1) - MNU_DrawSmallString(XDIM - OPT_XS - dx, OPT_LINE(0)+PGSIZ*8, morestr, 8,16); - } -#undef PGSIZ - } - - return TRUE; -} - -static int MNU_SelectButtonFunction(const char *buttonname, int *currentfunc) -{ - // Todo: Branch off to the generic keybind menu. - const int PGSIZ = 9; - const char *strs[] = { "Select the function to assign to", "%s", "or ESCAPE to cancel." }; - int topitem = 0, botitem = NUMGAMEFUNCTIONS; - int i, j, y; - short w, h=0; - int returnval = 0; - - if (inputState.GetKeyStatus(sc_Escape)) - { - inputState.ClearKeyStatus(sc_Escape); - returnval = -1; - } - else if (inputState.GetKeyStatus(sc_Home)) - { - *currentfunc = 0; - inputState.ClearKeyStatus(sc_Home); - } - else if (inputState.GetKeyStatus(sc_End)) - { - *currentfunc = NUMGAMEFUNCTIONS; - inputState.ClearKeyStatus(sc_End); - } - else if (inputState.GetKeyStatus(sc_PgDn)) - { - *currentfunc += PGSIZ; - if (*currentfunc > NUMGAMEFUNCTIONS) *currentfunc = NUMGAMEFUNCTIONS; - inputState.ClearKeyStatus(sc_PgDn); - } - else if (inputState.GetKeyStatus(sc_PgUp)) - { - *currentfunc -= PGSIZ; - if (*currentfunc < 0) *currentfunc = 0; - inputState.ClearKeyStatus(sc_PgUp); - } - else if (I_GeneralTrigger()) - { - I_GeneralTriggerClear(); - returnval = 1; - } - else if (I_MenuUp()) - { - I_MenuUpClear(); - *currentfunc = max(0, *currentfunc - 1); - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - //*currentfunc = min(NUMGAMEFUNCTIONS, *currentfunc + 1); - } - - - if (NUMGAMEFUNCTIONS > PGSIZ) - { - topitem = *currentfunc - PGSIZ/2; - botitem = topitem + PGSIZ; - - if (topitem < 0) - { - botitem += -topitem; - topitem = 0; - } - else if (botitem > NUMGAMEFUNCTIONS) - { - botitem = NUMGAMEFUNCTIONS; - topitem = botitem - PGSIZ; - } - } - - y = OPT_LINE(0); - for (i=0; i<(int)SIZ(strs); i++) - { - w = 0; - sprintf(ds, strs[i], buttonname); - for (j=0; ds[j]; j++) if (ds[j] == '_') ds[j] = ' '; - MNU_MeasureString(ds, &w, &h); - MNU_DrawString((XDIM - w)/2, y, ds, 0, 16); - y += h; - } - - for (i = topitem; i <= botitem; i++) - { - if (i == 0) - { - strcpy(ds, " -none-"); - } - else - { - auto c = buttonMap.GetButtonName(i-1); - for (j = 0; c[j]; j++) - { - if (c[j] == '_') ds[j] = ' '; - else ds[j] = c[j]; - } - ds[j] = 0; - } - - j = OPT_LINE(4)+(i-topitem)*8; - MNU_DrawSmallString(130, j, ds, (i == *currentfunc) ? 0 : 12, 16); - } - - { - short dx = 0, dy = 8; - const char *morestr = "More..."; - - MNU_MeasureSmallString(morestr,&dx,&dy); - if (topitem > 0) - MNU_DrawSmallString(XDIM - OPT_XS - dx, OPT_LINE(4), morestr, 8,16); - if (botitem < NUMGAMEFUNCTIONS) - MNU_DrawSmallString(XDIM - OPT_XS - dx, OPT_LINE(4)+PGSIZ*8, morestr, 8,16); - } - - return returnval; -} - - -static MenuItem_p mouse_button_item = NULL; - -static SWBOOL MNU_MouseButtonPostProcess(MenuItem_p item) -{ - mouse_button_item = item; - return TRUE; -} - -SWBOOL MNU_MouseButtonSetupCustom(UserCall call, MenuItem_p item) -{ - // Mouse buttons are now handled as normal keybinds - return TRUE; -} - -static SWBOOL MNU_SetMouseButtonFunctions(MenuItem_p item) -{ - // Mouse buttons are now handled as normal keybinds - return TRUE; -} - - -static MenuItem_p mouse_digital_item = NULL; - -static SWBOOL MNU_MouseDigitalPostProcess(MenuItem_p item) -{ - mouse_digital_item = item; - return TRUE; -} - -static SWBOOL MNU_MouseDigitalSetupCustom(UserCall call, MenuItem_p item) -{ - // obsolete - return TRUE; -} - -static SWBOOL MNU_SetAdvancedMouseFunctions(MenuItem_p item) -{ - // obsolete - return TRUE; -} - - -static MenuItem_p joystick_button_item = NULL; - -static SWBOOL MNU_JoystickButtonsInitialise(MenuItem_p mitem) -{ - MenuItem_p item; - MenuItem templayer = { DefLayer(0, JoystickButtonNames[0], &joybuttonsgroup), OPT_XS, OPT_LINE(0), 1, m_defshade, 0, NULL, NULL, MNU_JoystickButtonPostProcess }; - MenuItem tempinert = { DefInert(0, JoystickButtonFunctions[0]), OPT_XSIDE, OPT_LINE(0), 1, m_defshade, 0, NULL, MNU_SetJoystickButtonFunctions, NULL }; - MenuItem temppagename = { DefInert(0, JoystickButtonPageName[0]), OPT_XS, OPT_LINE(JOYSTICKITEMSPERPAGE+1), 1, m_defshade, 0, NULL, NULL, NULL }; - MenuItem tempnextpage = { DefOption(0, "Next..."), OPT_XSIDE, OPT_LINE(JOYSTICKITEMSPERPAGE+1), 1, m_defshade, 0, MNU_JoystickButtonNextPage, NULL, NULL }; - MenuItem tempnone = { DefNone }; - const char *hatdirs[] = { " Up", " Right", " Down", " Left" }; - int button, page, pageitem; - - if (joybuttonssetupgroup.items != NULL) - { - return TRUE; - } - - page = 0; - pageitem = 0; - joybuttonssetupgroup.items = joybuttons_i[0]; - item = &joybuttons_i[0][0]; - - for (button = 0; button < joystick.numButtons * 2 + (joystick.numHats > 0) * 4; ) - { - if (button < joystick.numButtons * 2) - { - int dbutton = button / 2; - - strcpy(JoystickButtonNames[dbutton], joyGetName(1, dbutton)); - - templayer.text = JoystickButtonNames[dbutton]; - templayer.y = OPT_LINE(pageitem); - templayer.tics = dbutton; - memcpy(item, &templayer, sizeof(MenuItem)); - item++; - - tempinert.text = JoystickButtonFunctions[dbutton]; - tempinert.y = OPT_LINE(pageitem); - tempinert.tics = dbutton; - memcpy(item, &tempinert, sizeof(MenuItem)); - item++; - - pageitem++; - - strcpy(JoystickButtonNames[dbutton + MAXJOYBUTTONS], "Double "); - strcat(JoystickButtonNames[dbutton + MAXJOYBUTTONS], joyGetName(1, dbutton)); - - templayer.text = JoystickButtonNames[dbutton + MAXJOYBUTTONS]; - templayer.y = OPT_LINE(pageitem); - templayer.tics = 128 | dbutton; - memcpy(item, &templayer, sizeof(MenuItem)); - item++; - - tempinert.text = JoystickButtonFunctions[dbutton + MAXJOYBUTTONS]; - tempinert.y = OPT_LINE(pageitem); - tempinert.tics = 128 | dbutton; - memcpy(item, &tempinert, sizeof(MenuItem)); - item++; - - pageitem++; - - button += 2; - } - else - { - int dir = button - joystick.numButtons * 2; - int dbutton = joystick.numButtons + dir; - - strcpy(JoystickButtonNames[dbutton], joyGetName(2, 0)); - strcat(JoystickButtonNames[dbutton], hatdirs[dir]); - - templayer.text = JoystickButtonNames[dbutton]; - templayer.y = OPT_LINE(pageitem); - templayer.tics = dbutton; - memcpy(item, &templayer, sizeof(MenuItem)); - item++; - - tempinert.text = JoystickButtonFunctions[dbutton]; - tempinert.y = OPT_LINE(pageitem); - tempinert.tics = dbutton; - memcpy(item, &tempinert, sizeof(MenuItem)); - item++; - - pageitem++; - button++; - } - - if (pageitem == JOYSTICKITEMSPERPAGE || button == joystick.numButtons * 2 + (joystick.numHats > 0) * 4) - { - // next page - sprintf(JoystickButtonPageName[page], "Page %d / %d", page+1, - ((joystick.numButtons * 2 + (joystick.numHats > 0) * 4) / JOYSTICKITEMSPERPAGE) + 1); - - temppagename.text = JoystickButtonPageName[page]; - memcpy(item, &temppagename, sizeof(MenuItem)); - item++; - - memcpy(item, &tempnextpage, sizeof(MenuItem)); - item++; - - memcpy(item, &tempnone, sizeof(MenuItem)); - - page++; - pageitem = 0; - item = &joybuttons_i[page][0]; - } - } - - return TRUE; -} - -static SWBOOL MNU_JoystickButtonPostProcess(MenuItem_p item) -{ - joystick_button_item = item; - return TRUE; -} - -static SWBOOL MNU_JoystickButtonSetupCustom(UserCall call, MenuItem *item) -{ - // controller buttons are being handled as keybinds now - return TRUE; -} - -static SWBOOL MNU_JoystickButtonNextPage(void) -{ - JoystickButtonPage = (JoystickButtonPage + 1) % (((joystick.numButtons * 2 + (joystick.numHats > 0) * 4) / JOYSTICKITEMSPERPAGE) + 1); - joybuttonssetupgroup.items = &joybuttons_i[JoystickButtonPage][0]; - joybuttonssetupgroup.cursor = 0; - MNU_ItemPreProcess(&joybuttonssetupgroup); - return TRUE; -} - -static SWBOOL MNU_SetJoystickButtonFunctions(MenuItem_p item) -{ - // controller buttons are being handled as keybinds now - return TRUE; -} - - -static MenuItem_p joystick_axis_item = NULL; - -static SWBOOL MNU_JoystickAxesInitialise(MenuItem_p mitem) -{ -#if 0 - if (!CONTROL_JoyPresent) - { - return TRUE; - } - if (JoystickAxisPage < 0 || JoystickAxisPage >= joystick.numAxes) - { - JoystickAxisPage = 0; - } - - strcpy(JoystickAxisName, joyGetName(0, JoystickAxisPage)); - sprintf(JoystickAxisPageName, "Page %d / %d", JoystickAxisPage+1, joystick.numAxes); - slidersettings[sldr_joyaxisanalog] = MNU_ControlAxisOffset(JoystickAnalogAxes[JoystickAxisPage]); - slidersettings[sldr_joyaxisscale] = JoystickAnalogScale[JoystickAxisPage] >> 13; - slidersettings[sldr_joyaxisdead] = JoystickAnalogDead[JoystickAxisPage] >> 10; - slidersettings[sldr_joyaxissatur] = JoystickAnalogSaturate[JoystickAxisPage] >> 10; -#endif - return TRUE; -} - -static SWBOOL MNU_JoystickAxisPostProcess(MenuItem_p item) -{ - joystick_axis_item = item; - return TRUE; -} - -static SWBOOL MNU_JoystickAxisSetupCustom(UserCall call, MenuItem *item) -{ -#if 0 - static int currentfunc = 0; - - if (call == uc_touchup) - return TRUE; - - if (cust_callback == NULL) - { - if (call != uc_setup) - return FALSE; - - currentfunc = JoystickDigitalAxes[JoystickAxisPage][joystick_axis_item->tics]; - currentfunc++; - - cust_callback = MNU_JoystickAxisSetupCustom; - cust_callback_call = call; - cust_callback_item = item; - } - - { - short w, h = 0; - const char *s = "Joystick Axes"; - - rotatesprite(10 << 16, (5-3) << 16, MZ, 0, 2427, - m_defshade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); - MNU_MeasureStringLarge(s, &w, &h); - MNU_DrawStringLarge(TEXT_XCENTER(w), 5, s); - } - - int selection = MNU_SelectButtonFunction(joystick_axis_item->text, ¤tfunc); - switch (selection) - { - case -1: //cancel - cust_callback = NULL; - break; - case 1: //acknowledge - currentfunc--; - JoystickDigitalAxes[JoystickAxisPage][joystick_axis_item->tics] = currentfunc; - CONTROL_MapDigitalAxis(JoystickAxisPage, currentfunc, joystick_axis_item->tics, controldevice_joystick); - MNU_SetJoystickAxisFunctions(joystick_axis_item); - cust_callback = NULL; - break; - default: break; - } -#endif - return TRUE; -} - -static SWBOOL MNU_JoystickAxisNextPage(void) -{ - JoystickAxisPage = (JoystickAxisPage + 1) % MNU_ControlAxisOffset(analog_maxtype); - joyaxessetupgroup.cursor = 1; - MNU_ItemPreProcess(&joyaxessetupgroup); - MNU_JoystickAxesInitialise(NULL); - return TRUE; -} - -static SWBOOL MNU_SetJoystickAxisFunctions(MenuItem_p item) -{ -#if 0 - int function; - char *p; - - function = JoystickDigitalAxes[JoystickAxisPage][item->tics]; - if (function < 0) - { - strcpy(JoystickAxisFunctions[item->tics], " -"); - } - else - { - strcpy(JoystickAxisFunctions[item->tics], buttonMap.GetButtonName(function)); - for (p = JoystickAxisFunctions[item->tics]; *p; p++) - { - if (*p == '_') - *p = ' '; - } - } -#endif - return TRUE; -} - - -SWBOOL -MNU_OrderCustom(UserCall call, MenuItem *item) -{ - static signed char on_screen = 0,last_screen = 0; - static int limitmove=0; - SWBOOL select_held = FALSE; - int zero = 0; - static SWBOOL DidOrderSound = FALSE; - short choose_snd; - static int wanghandle; - - static short RegOrderScreen[] = - { - // 5262, - // 5261, - 5111, - 5118, - 4979, - 5113, - - 5120 // 5114 // JBF: for my credits - }; - static short SWOrderScreen[] = - { - 5110, - 5112, - // 5262, - 5111, - 5118, - 4979, - 5113, - - 5120 // 5114 // JBF: for my credits - }; - short *OrderScreen, OrderScreenSiz; - - if (SW_SHAREWARE) - { - OrderScreen = SWOrderScreen; - OrderScreenSiz = SIZ(SWOrderScreen); - } - else - { - OrderScreen = RegOrderScreen; - OrderScreenSiz = SIZ(RegOrderScreen); - } - - // Ignore the special touchup calls - if (call == uc_touchup) - return TRUE; - - if (cust_callback == NULL) - { - if (call != uc_setup) - return FALSE; - } - - if (SW_SHAREWARE && on_screen == 0 && !DidOrderSound) - { - DidOrderSound = TRUE; - choose_snd = STD_RANDOM_RANGE(1000); - if (choose_snd > 500 && !FX_SoundValidAndActive(wanghandle)) - wanghandle = PlaySound(DIGI_WANGORDER1, &zero, &zero, &zero, v3df_dontpan); - else if (!FX_SoundValidAndActive(wanghandle)) - wanghandle = PlaySound(DIGI_WANGORDER2, &zero, &zero, &zero, v3df_dontpan); - } - - if (!select_held) - { - //order_input_buffered.dir = tst_input.dir; - // Support a few other keys too - if (inputState.GetKeyStatus(KEYSC_SPACE)||inputState.GetKeyStatus(KEYSC_ENTER)) - { - inputState.ClearKeyStatus(KEYSC_SPACE); - inputState.ClearKeyStatus(KEYSC_ENTER); - //tst_input.dir = dir_South; - } - } - -#if 0 - if (inputState.GetKeyStatus(KEY_MOUSE1)) - { - if (tst_input.button0 == order_input_buffered.button0 && - tst_input.button1 == order_input_buffered.button1 && - tst_input.dir == order_input_buffered.dir) - { - select_held = TRUE; - } - else - { - if (labs((int32_t) totalclock - limitmove) > 7) - { - order_input.button0 = order_input_buffered.button0; - order_input.button1 = order_input_buffered.button1; - order_input.dir = order_input_buffered.dir; - - order_input_buffered.button0 = tst_input.button0; - order_input_buffered.button1 = tst_input.button1; - order_input_buffered.dir = tst_input.dir; - - limitmove = (int32_t) totalclock; - } - } - } - else - { - select_held = FALSE; - order_input_buffered.button0 = tst_input.button0; - order_input_buffered.button1 = tst_input.button1; - order_input_buffered.dir = tst_input.dir; - } -#endif - - if (!inputState.GetKeyStatus(KEYSC_ESC)) - { - cust_callback = MNU_OrderCustom; - cust_callback_call = call; - cust_callback_item = item; - } - else - { - inputState.ClearKeyStatus(sc_Escape); - cust_callback = NULL; - DidOrderSound = FALSE; - on_screen = 0; - ExitMenus(); - } - - if (I_MenuUp()) - { - I_MenuUpClear(); - on_screen--; - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - on_screen++; - } - else if (I_MenuLeft()) - { - I_MenuLeftClear(); - on_screen--; - } - else if (I_MenuRight()) - { - I_MenuRightClear(); - on_screen++; - } - -// CTW MODIFICATION -// I reversed the logic in here to allow the user to loop around. -// Yeah... I changed default behavior just because I wanted to. -// AND YOU CAN'T STOP ME SUCKER!!! - if (on_screen < 0) - on_screen = OrderScreenSiz-1; - - if (on_screen > OrderScreenSiz-1) - on_screen = 0; -// CTW MODIFICATION END - - int const shade = on_screen == OrderScreenSiz-1 ? 8 : 0; - rotatesprite(0,0,RS_SCALE,0,OrderScreen[on_screen], shade, 0, - (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK|ROTATE_SPRITE_IGNORE_START_MOST), - 0, 0, xdim-1, ydim-1); - - if (on_screen == OrderScreenSiz-1) - { - // Jonathon's credits page hack :-) - - static const char *jtitle = "^Port Credits"; - static const char *jtext[] = - { - "*Developers", - " Richard \"TerminX\" Gobeille", - " Evan \"Hendricks266\" Ramos", - " Alex \"pogokeen\" Dawson", - "*Retired developers", - " Pierre-Loup \"Plagman\" Griffais", - " Philipp \"Helixhorned\" Kutin", - "*Special thanks to", - " Jonathon \"JonoF\" Fowler", - "*Uses BUILD Engine technology by", - " Ken \"Awesoken\" Silverman", - "*Additional thanks to", - " Alexey \"Nuke.YKT\" Skrybykin", - " Jordon \"Striker\" Moss", - " Par \"Parkar\" Karlsson", // "Pär \"Parkar\" Karlsson", - " Ben \"ProAsm\" Smit", - " NY00123", - "-", - " Visit eduke32.com for news and updates" - }; -#if 0 - static const char *scroller[] = - { - "Thanks to these people for their input and contributions:", - "", - "", - "and all those who submitted bug reports and ", - "supported the project financially!", - "", - "", - "--x--", - "", - "", - "", - "" - }; -#endif - short dimx, dimy; - int ycur = 20; - unsigned ji; - - dimy = 0; MNU_MeasureString(jtitle, &dimx, &dimy); - MNU_DrawString(160-(dimx>>1), ycur, jtitle, 0, 0); - ycur += dimy + 8; - - for (ji = 0; ji < SIZ(jtext); ji++) - { - switch (jtext[ji][0]) - { - case '-': - ycur += 6; - break; - case '*': - dimx = dimy = 0; - MNU_MeasureString(&jtext[ji][1], &dimx, &dimy); - MNU_DrawString(160-(dimx>>1), ycur, &jtext[ji][1], 0, 16); - ycur += dimy+1; - break; - default: - if (ji>0 && jtext[ji-1][0] == '*') ycur += 3; - dimx = dimy = 0; - MNU_MeasureSmallString(&jtext[ji][1], &dimx, &dimy); - MNU_DrawSmallString(160-(dimx>>1), ycur, &jtext[ji][1], 0, 0); - ycur += dimy+1; - break; - } - } - -#if 0 - const int numscrollerlines = SIZ(scroller); - int m,i; - for (m=0, i=((int32_t) totalclock/104)%numscrollerlines; m<4; m++,i++) - { - if (i == numscrollerlines) - i=0; - dimx = dimy = 0; - MNU_MeasureSmallString(scroller[i], &dimx, &dimy); - MNU_DrawSmallString(160-(dimx>>1), 154+(m*7), scroller[i], 0, 8); - } -#endif - } - - //inputState.ClearKeysDown(); - - return TRUE; -} - -SWBOOL MNU_LoadModernDefaults(void) -{ - //SetDefaultKeyDefinitions(1); - //SetMouseDefaults(1); - return TRUE; -} - -SWBOOL MNU_LoadClassicDefaults(void) -{ - //SetDefaultKeyDefinitions(0); - //SetMouseDefaults(0); - return TRUE; -} - - -short EpisodeMenuSelection; - -void -ExitMenus(void) -{ - ControlPanelType = ct_mainmenu; - UsingMenus = FALSE; - - if (LoadGameOutsideMoveLoop) - return; - - ResumeGame(); - SetRedrawScreen(&Player[myconnectindex]); -} - -SWBOOL -MNU_StartGame(void) -{ - PLAYERp pp = Player + screenpeek; - int handle = 0; - int zero = 0; - - // always assumed that a demo is playing - - ready2send = 0; - Skill = currentmenu->cursor; - - if (EpisodeMenuSelection >= 1) - Level = 5; - else - Level = 1; - - ExitMenus(); - DemoPlaying = FALSE; - ExitLevel = TRUE; - NewGame = TRUE; - DemoMode = FALSE; - CameraTestMode = FALSE; - - //InitNewGame(); - - if (Skill == 0) - handle = PlaySound(DIGI_TAUNTAI3,&zero,&zero,&zero,v3df_none); - else if (Skill == 1) - handle = PlaySound(DIGI_NOFEAR,&zero,&zero,&zero,v3df_none); - else if (Skill == 2) - handle = PlaySound(DIGI_WHOWANTSWANG,&zero,&zero,&zero,v3df_none); - else if (Skill == 3) - handle = PlaySound(DIGI_NOPAIN,&zero,&zero,&zero,v3df_none); - - if (handle > FX_Ok) - while (FX_SoundActive(handle)) - handleevents(); - - return TRUE; -} - -void ResetMenuInput(void) -{ - cust_callback = NULL; - InputMode = FALSE; -} - SWBOOL MNU_StartNetGame(void) { @@ -1596,16 +83,13 @@ MNU_StartNetGame(void) ready2send = 0; // Skill can go negative here - Skill = gs.NetMonsters-1; + Skill = gs.NetMonsters - 1; Level = gs.NetLevel + 1; - if (!AutoNet) - ExitMenus(); DemoPlaying = FALSE; ExitLevel = TRUE; NewGame = TRUE; // restart demo for multi-play mode DemoInitOnce = FALSE; - ResetMenuInput(); // TENSW: return if a joiner if (/* CTW REMOVED gTenActivated && */ !AutoNet && FirstTimeIntoGame) @@ -1617,8 +101,8 @@ MNU_StartNetGame(void) gNet.SpawnMarkers = gs.NetSpawnMarkers; gNet.HurtTeammate = gs.NetHurtTeammate; gNet.Nuke = gs.NetNuke; - gNet.KillLimit = gs.NetKillLimit*10; - gNet.TimeLimit = TimeLimitTable[gs.NetTimeLimit]*60*120; + gNet.KillLimit = gs.NetKillLimit * 10; + gNet.TimeLimit = TimeLimitTable[gs.NetTimeLimit] * 60 * 120; if (ShortGameMode) { @@ -1628,7 +112,7 @@ MNU_StartNetGame(void) gNet.TimeLimitClock = gNet.TimeLimit; gNet.TeamPlay = gs.NetTeamPlay; - gNet.MultiGameType = gs.NetGameType+1; + gNet.MultiGameType = gs.NetGameType + 1; if (gNet.MultiGameType == MULTI_GAME_COMMBAT_NO_RESPAWN) { @@ -1664,251 +148,16 @@ MNU_StartNetGame(void) } -SWBOOL -MNU_EpisodeCustom(void) -{ - EpisodeMenuSelection = currentmenu->cursor; - - return TRUE; -} - -SWBOOL -MNU_QuitCustom(UserCall call, MenuItem_p item) -{ - int select; - int ret; - extern SWBOOL DrawScreen; - - // Ignore the special touchup calls - if (call == uc_touchup) - return TRUE; - - if (cust_callback == NULL) - { - if (call != uc_setup) - return FALSE; - - memset(dialog, 0, sizeof(dialog)); - - dialog[0] = S_QUITYN; - } - - ret = MNU_Dialog(); - - if (DrawScreen) - return TRUE; - - if (!ret) - { - if (!inputState.GetKeyStatus(KEY_MOUSE1) && !inputState.GetKeyStatus(sc_N)) - { - cust_callback = MNU_QuitCustom; - cust_callback_call = call; - cust_callback_item = item; - } - else - { - cust_callback = NULL; - ExitMenus(); - } - } - else - { - cust_callback = NULL; - ExitMenus(); - } - - if (inputState.GetKeyStatus(sc_Y) || inputState.GetKeyStatus(sc_Enter) || inputState.GetKeyStatus(KEY_MOUSE1)) - { - if (CommPlayers >= 2) - MultiPlayQuitFlag = TRUE; - else - QuitFlag = TRUE; - - ExitMenus(); - } - - inputState.ClearKeysDown(); - - return TRUE; -} - -SWBOOL -MNU_QuickLoadCustom(UserCall call, MenuItem_p item) -{ - int select; - extern SWBOOL ReloadPrompt; - int bak; - PLAYERp pp = Player + myconnectindex; - extern short GlobInfoStringTime; - extern SWBOOL DrawScreen; - int ret; - - if (cust_callback == NULL) - { - if (call != uc_setup) - return FALSE; - - memset(dialog, 0, sizeof(dialog)); - - dialog[0] = "Load saved game"; - sprintf(QuickLoadDescrDialog,"\"%s\" (Y/N)?",SaveGameDescr[QuickLoadNum]); - dialog[1] = QuickLoadDescrDialog; - } - - // Ignore the special touchup calls - if (call == uc_touchup) - return TRUE; - - ret = MNU_Dialog(); - - if (DrawScreen) - { - return TRUE; - } - - if (ret == FALSE) - { - if (inputState.GetKeyStatus(sc_N) || inputState.GetKeyStatus(sc_Space) || inputState.GetKeyStatus(sc_Enter)) - { - cust_callback = NULL; - if (ReloadPrompt) - { - ReloadPrompt = FALSE; - bak = GlobInfoStringTime; - GlobInfoStringTime = 999; - PutStringInfo(pp, "Press SPACE to restart"); - GlobInfoStringTime = bak; - } - - inputState.ClearKeysDown(); - ExitMenus(); - } - else - { - cust_callback = MNU_QuickLoadCustom; - cust_callback_call = call; - cust_callback_item = item; - } - } - else - { - // Y pressed - cust_callback = NULL; - - LoadSaveMsg("Loading..."); - - if (DoQuickLoad() == FALSE) - { - ResumeAction(); - return FALSE; - } - - ExitMenus(); - - return TRUE; - } - - inputState.ClearKeysDown(); - - return TRUE; -} - -// MENU FUNCTIONS ///////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////// -// Set some global menu related defaults -//////////////////////////////////////////////// -void -MNU_InitMenus(void) -{ - pClearTextLine(Player + myconnectindex, TEXT_INFO_LINE(0)); - - slidersettings[sldr_mouse] = in_mousesensitivity; // (MOUSE_SENS_MAX_VALUE / SLDR_MOUSESENSEMAX); - - slidersettings[sldr_sndfxvolume] = snd_fxvolume / (FX_VOL_MAX_VALUE/SLDR_SNDFXVOLMAX); - slidersettings[sldr_musicvolume] = mus_volume / (MUSIC_VOL_MAX_VALUE/SLDR_MUSICVOLMAX); - slidersettings[sldr_scrsize] = gs.BorderNum; - slidersettings[sldr_brightness] = 10; - slidersettings[sldr_bordertile] = gs.BorderTile; - - { - int i,newx=xdim,newy=ydim; - - buttonsettings[btn_videofs] = fullscreen; - - UpdateValidModes(bpp,fullscreen); - for (i=0; i= 0) - for (i=0; i>13; - //slidersettings[sldr_mousescaley] = MouseAnalogScale[1]>>13; - - slidersettings[sldr_joyaxisscale] = 0; - slidersettings[sldr_joyaxisanalog] = 0; - slidersettings[sldr_joyaxisdead] = 0; - slidersettings[sldr_joyaxissatur] = 0; - - // Distinguish between Single or Multiplay for new game menu types - if (numplayers > 1) - main_i[0].child = &networkgroup; - else -// #ifdef SW_SHAREWARE - main_i[0].child = &episodegroup; -// #else -// main_i[0].child = &skillgroup; -// #endif - main_i[4].text = (SW_SHAREWARE) ? MAIN_MENU_HOW_TO_ORDER : MAIN_MENU_COOL_STUFF; - main_i[4].hotkey = (SW_SHAREWARE) ? KEYSC_H : KEYSC_C; -} - //////////////////////////////////////////////// // Measure the pixel width of a graphic string //////////////////////////////////////////////// -static char lg_xlat_num[] = {0,1,2,3,4,5,6,7,8,9}; +static char lg_xlat_num[] = { 0,1,2,3,4,5,6,7,8,9 }; #define FONT_LARGE_ALPHA 3706 #define FONT_LARGE_DIGIT 3732 +#define MenuDrawFlags (ROTATE_SPRITE_SCREEN_CLIP) +#define MZ 65536 +#define MENU_SHADE_DEFAULT 0 +#define MENU_SHADE_INACTIVE 20 void MNU_MeasureStringLarge(const char *string, short *w, short *h) { @@ -1952,7 +201,7 @@ void MNU_MeasureStringLarge(const char *string, short *w, short *h) //////////////////////////////////////////////// // Draw a string using a graphic font //////////////////////////////////////////////// -void MNU_DrawStringLarge(short x, short y, const char *string) +void MNU_DrawStringLarge(short x, short y, const char *string, int shade) { int ndx, offset; char c; @@ -1981,7 +230,7 @@ void MNU_DrawStringLarge(short x, short y, const char *string) continue; } - rotatesprite(offset << 16, y << 16, MZ, 0, pic, MenuTextShade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + rotatesprite(offset << 16, y << 16, MZ, 0, pic, shade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); offset += tilesiz[pic].x + 1; } @@ -2061,34 +310,6 @@ void MNU_DrawString(short x, short y, const char *string, short shade, short pal } } -/* Original code -void -MNU_DrawString(short x, short y, char *string) -{ - int ndx, offset; - char c; - - if (string[0] == '^') - { - MNU_DrawStringLarge(x,y, &string[1]); - return; - } - - offset = x; - - for (ndx = 0; (c = string[ndx]) != 0; ndx++) - { - if (c > asc_Space && c < 127) - { - rotatesprite(offset << 16, y << 16, MZ, 0, xlatfont[c], MenuTextShade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - offset += tilesiz[xlatfont[c]].x; - } else - if (c == asc_Space) - offset += 4; // Special case for space char - } - -} -*/ //////////////////////////////////////////////// // Measure the pixel width of a small font string @@ -2155,2309 +376,6 @@ void MNU_DrawSmallString(short x, short y, const char *string, short shade, shor } -//////////////////////////////////////////////// -// Get an input string from user using small font -//////////////////////////////////////////////// - -signed char MNU_InputSmallString(char *name, short pix_width) -{ - char ch; - short w, h; - -#define ascii_backspace 8 -#define ascii_esc 27 -#define ascii_return 13 - - if (!MoveSkip4 && !MessageInputMode) - { - if (I_MenuUp()) - { - CON_CommandHistory(1); - } - else if (I_MenuDown()) - { - CON_CommandHistory(-1); - } - } - - while (inputState.keyBufferWaiting()) - { - ch = inputState.keyGetChar(); - - // skip any extended key - if (ch == 0) - { - ch = inputState.keyGetChar(); - if (ch == 104) // extended enter - ch = ascii_return; - else - continue; - } - - if (ch == ascii_backspace) - { - name[strlen(name) - 1] = '\0'; - continue; - } - else if (ch == ascii_esc) - { - return -1; - } - else if (ch == ascii_return) - { - return FALSE; - } - else if (!isprint(ch)) - continue; - - MNU_MeasureSmallString(name, &w, &h); - if (w < pix_width) - { - size_t const namelen = strlen(name); - if (namelen < 256) // Dont let it go too far! - { - name[namelen] = ch; - name[namelen+1] = '\0'; - } - } - } - - return TRUE; - -} - -//////////////////////////////////////////////// -// Draw dialog text on screen -//////////////////////////////////////////////// -static SWBOOL MNU_Dialog(void) -{ - short ndx, linecnt, w[MAXDIALOG], h, x, y; - - linecnt = 0; - h = 8; - - for (ndx = 0; ndx < MAXDIALOG && dialog[ndx]; ndx++) - { - MNU_MeasureString(dialog[ndx], &w[ndx], &h); - ASSERT(w[ndx] < XDIM); - linecnt++; - } - - y = ((YDIM - ((h * linecnt) + (linecnt * 2))) / 2); - - for (ndx = 0; ndx < linecnt; ndx++) - { - x = ((XDIM - w[ndx]) / 2); - MNU_DrawString(x, y, dialog[ndx],1,16); - y += (h + 3); - } - - if (inputState.GetKeyStatus(sc_Y) || inputState.GetKeyStatus(sc_Enter) || inputState.GetKeyStatus(KEY_MOUSE1)) - return TRUE; - else - return FALSE; -} - -//////////////////////////////////////////////// -// Get an input string from user -//////////////////////////////////////////////// - -signed char MNU_InputString(char *name, short pix_width) -{ - char ch; - short w, h; - -#define ascii_backspace 8 -#define ascii_esc 27 -#define ascii_return 13 - - while (inputState.keyBufferWaiting()) - { - ch = inputState.keyGetChar(); - - ////DSPRINTF(ds, "%c %d", ch, ch); - //MONO_PRINT(ds); - - // skip most extended keys - if (ch == 0) - { - ch = inputState.keyGetChar(); - - ////DSPRINTF(ds, "extended key %c %d", ch, ch); - //MONO_PRINT(ds); - - if (ch == 104) // extended enter - ch = ascii_return; - else - continue; - } - - if (ch == ascii_backspace) - { - name[strlen(name) - 1] = '\0'; - continue; - } - else if (ch == ascii_esc) - { - return -1; - } - else if (ch == ascii_return) - { - return FALSE; - } - else if (!isprint(ch)) - continue; - - MNU_MeasureString(name, &w, &h); - if (w < pix_width) - { - size_t const namelen = strlen(name); - name[namelen] = ch; - name[namelen+1] = '\0'; - } - } - - return TRUE; - -} - -#define SS_XSTART 146L -#define SS_YSTART SD_YSTART -#define SS_BORDER_SIZE 5L - -void LoadSaveMsg(const char *msg) -{ - short w,h; - - renderFlushPerms(); - DrawMenuLevelScreen(); - strcpy(ds, msg); - MNU_MeasureString(ds, &w, &h); - MNU_DrawString(TEXT_XCENTER(w), 170, ds, 1, 16); - videoNextPage(); -} - - -//////////////////////////////////////////////// -// Load Game menu -// This function gets called whenever you -// press enter on one of the load game -// spots. -// I'm figuring it need to do the following: -// . Load the game if there is one by calling: MNU_LoadGameCustom. -//////////////////////////////////////////////// -SWBOOL MNU_GetLoadCustom(void) -{ - short load_num; - - load_num = currentmenu->cursor; - - // no saved game exists - don't do anything - if (SaveGameDescr[load_num][0] == '\0') - return FALSE; - - if (InMenuLevel || DemoMode || DemoPlaying) - { - LoadSaveMsg("Loading..."); - - if (LoadGame(load_num) == -1) - return FALSE; - - QuickLoadNum = load_num; - // the (Quick)Save menu should default to the last loaded game - SaveGameGroup.cursor = load_num; - - ExitMenus(); - ExitLevel = TRUE; - LoadGameOutsideMoveLoop = TRUE; - if (DemoMode || DemoPlaying) - LoadGameFromDemo = TRUE; - - return TRUE; - } - - LoadSaveMsg("Loading..."); - - PauseAction(); - - if (LoadGame(load_num) == -1) - { - ResumeAction(); - return FALSE; - } - - QuickLoadNum = load_num; - // the (Quick)Save menu should default to the last loaded game - SaveGameGroup.cursor = load_num; - - ready2send = 1; - LastSaveNum = -1; - ExitMenus(); - - if (DemoMode) - { - ExitLevel = TRUE; - DemoPlaying = FALSE; - } - - return TRUE; -} - -//////////////////////////////////////////////// -// Save Game menu -// This function gets called whenever you -// press enter on one of the save game -// spots. -// I'm figuring it need to do the following: -// . Call MNU_GetInput to allow string input of description. -// . Save the game if there is one by calling: MNU_SaveGameCustom. -//////////////////////////////////////////////// -SWBOOL MNU_GetSaveCustom(void) -{ - short save_num; - extern SWBOOL InMenuLevel, LoadGameOutsideMoveLoop; - - save_num = currentmenu->cursor; - - if (InMenuLevel) - return FALSE; - - if (MenuInputMode) - { - LoadSaveMsg("Saving..."); - - if (DoQuickSave(save_num) == FALSE) - { - LoadGameGroup.cursor = save_num; - } - - ResumeAction(); - ExitMenus(); - - // toggle edit mode - MenuInputMode = FALSE; - } - else - { - strcpy(BackupSaveGameDescr, SaveGameDescr[save_num]); - - // clear keyboard buffer - while (inputState.keyBufferWaiting()) - { - if (inputState.keyGetChar() == 0) - inputState.keyGetChar(); - } - - // toggle edit mode - MenuInputMode = TRUE; - } - - return TRUE; -} - -//////////////////////////////////////////////// -// Load/Save Touchup function -// This function gets called each frame by DrawMenus -//////////////////////////////////////////////// - -static SWBOOL MNU_DrawLoadSave(short game_num) -{ - // screen border - rotatesprite(SS_XSTART << 16, SS_YSTART << 16, MZ, 0, pic_loadsavescreen, - 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); - - // description box - rotatesprite((SD_XSTART) << 16, (SD_YSTART) << 16, MZ, 0, pic_savedescr, - 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); - - // cursor for text boxes - rotatesprite((SD_XSTART + 3) << 16, (SD_LINE(game_num) + 1) << 16, MZ, 0, pic_loadsavecursor, - 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); - - return TRUE; -} - -static char SaveGameInfo1[80]; -static char SaveGameInfo2[80]; - - -SWBOOL MNU_LoadSaveMove(UserCall call, MenuItem_p item) -{ - short i; - short game_num; - short tile; - static short SaveGameEpisode, SaveGameLevel, SaveGameSkill; - SWBOOL GotInput = FALSE; - - if (!UsingMenus) - return TRUE; - - game_num = currentmenu->cursor; - - // read all descr first time through - LastSaveNum starts at 99 - if (LastSaveNum == 99) - { - memset(SaveGameDescr, '\0', sizeof(SaveGameDescr)); - - for (i = 0; i < 10; i++) - LoadGameDescr(i, SaveGameDescr[i]); - } - - // cursor has moved - read header - if (game_num != LastSaveNum) - { - screen_tile = LoadGameFullHeader(game_num, SaveGameDescr[game_num], - &SaveGameLevel, &SaveGameSkill); - - sprintf(SaveGameInfo1, "Level %d, Skill %d", SaveGameLevel, SaveGameSkill+1); - SaveGameInfo2[0] = 0; - } - - LastSaveNum = game_num; - - // input mode check - if (MenuInputMode) - { - MenuItem *item = ¤tmenu->items[currentmenu->cursor]; - - if (SavePrompt) - { - if (inputState.GetKeyStatus(sc_Y) || inputState.GetKeyStatus(sc_Enter)) - { - inputState.ClearKeyStatus(sc_Y); - inputState.ClearKeyStatus(sc_Enter); - SavePrompt = FALSE; - // use input - item->custom(); - } - else if (inputState.GetKeyStatus(sc_N)) - { - inputState.ClearKeyStatus(sc_N); - strcpy(SaveGameDescr[game_num], BackupSaveGameDescr); - SavePrompt = FALSE; - MenuInputMode = FALSE; - } - } - else - // get input - switch (MNU_InputString(SaveGameDescr[game_num], 114)) - { - case -1: // Cancel Input (pressed ESC) or Err - strcpy(SaveGameDescr[game_num], BackupSaveGameDescr); - MenuInputMode = FALSE; - inputState.ClearKeysDown(); - break; - case FALSE: // Input finished (RETURN) - // no input - if (SaveGameDescr[game_num][0] == '\0') - { - strcpy(SaveGameDescr[game_num], BackupSaveGameDescr); - MenuInputMode = FALSE; - } - else - { - GotInput = TRUE; - } - inputState.ClearKeyStatus(sc_Enter); - break; - case TRUE: // Got input - break; - } - - if (GotInput) - { - if (BackupSaveGameDescr[0]) - SavePrompt = TRUE; - - if (!SavePrompt) - { - // use input - item->custom(); - } - } - } - - return TRUE; -} - -SWBOOL MNU_LoadSaveDraw(UserCall call, MenuItem_p item) -{ - short i; - short game_num; - short tile; - - game_num = currentmenu->cursor; - - // misc drawing - MNU_DrawLoadSave(game_num); - - // print game descriptions - for (i = 0; i < 10; i++) - { - if (i == game_num && MenuInputMode && !SavePrompt) - { - static SWBOOL cur_show; - char tmp[sizeof(SaveGameDescr[0])*2]; - - //cur_show ^= 1; - cur_show = ((int32_t) totalclock & 32); - if (cur_show) - { - // add a cursor to the end - sprintf(tmp, "%s_", SaveGameDescr[i]); - } - else - strcpy(tmp, SaveGameDescr[i]); - - MNU_DrawString(SD_XSTART + 4, SD_YSTART + (i * SD_YOFF) + 2, tmp, 1, 16); - } - else if (SaveGameDescr[i][0] != '\0') - { - MNU_DrawString(SD_XSTART + 4, SD_YSTART + (i * SD_YOFF) + 2, SaveGameDescr[i], 1, 16); - } - } - - if (screen_tile != -1) - { - // draw 160x100 save screen - rotatesprite((SS_XSTART + SS_BORDER_SIZE) << 16, (SS_YSTART + SS_BORDER_SIZE) << 16, (1 << 16), 0 + 512, screen_tile, - 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER | ROTATE_SPRITE_NON_MASK | ROTATE_SPRITE_YFLIP, 0, 0, xdim - 1, ydim - 1); - - // draw info string - MNU_DrawString(SS_XSTART + 13, SS_YSTART + 100 + 10, SaveGameInfo1, 1, 16); - MNU_DrawString(SS_XSTART + 13, SS_YSTART + 100 + 18, SaveGameInfo2, 1, 16); - - if (SavePrompt) - { - MNU_DrawString(SS_XSTART + SS_BORDER_SIZE + 5, SS_YSTART + SS_BORDER_SIZE + 47, "Overwrite previous", 1, 16); - MNU_DrawString(SS_XSTART + SS_BORDER_SIZE + 5, SS_YSTART + SS_BORDER_SIZE + 47 + 12, " saved game (Y/N)", 1, 16); - } - } - else - { - // draw 160x100 black pic - rotatesprite((SS_XSTART + SS_BORDER_SIZE) << 16, (SS_YSTART + SS_BORDER_SIZE) << 16, (1 << 16), 0, pic_loadsavescreenbak, - 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER | ROTATE_SPRITE_NON_MASK, 0, 0, xdim - 1, ydim - 1); - - MNU_DrawString(SS_XSTART + SS_BORDER_SIZE + 60, SS_YSTART + SS_BORDER_SIZE + 47, "Empty", 1, 16); - } - - - return TRUE; -} - -SWBOOL MNU_ShareWareCheck(MenuItem *item) -{ - if (SW_SHAREWARE) - { - SET(item->flags, mf_disabled); - } - - return TRUE; -} - -SWBOOL MNU_CheckUserMap(MenuItem *item) -{ - if (UserMapName[0] == '\0') - RESET(item->flags, mf_disabled); - else - SET(item->flags, mf_disabled); - return TRUE; -} - -SWBOOL MNU_ShareWareMessage(MenuItem *item) -{ - const char *extra_text; - short w,h; - - if (SW_SHAREWARE) - { - extra_text = "Be sure to call 800-3DREALMS today"; - MNU_MeasureString(extra_text, &w, &h); - MNU_DrawString(TEXT_XCENTER(w), 110, extra_text, 1, 16); - extra_text = "and order the game."; - MNU_MeasureString(extra_text, &w, &h); - MNU_DrawString(TEXT_XCENTER(w), 120, extra_text, 1, 16); - extra_text = "You are only playing the first "; - MNU_MeasureString(extra_text, &w, &h); - MNU_DrawString(TEXT_XCENTER(w), 130, extra_text, 1, 16); - extra_text = "four levels, and are missing most"; - MNU_MeasureString(extra_text, &w, &h); - MNU_DrawString(TEXT_XCENTER(w), 140, extra_text, 1, 16); - extra_text = "of the game, weapons and monsters."; - MNU_MeasureString(extra_text, &w, &h); - MNU_DrawString(TEXT_XCENTER(w), 150, extra_text, 1, 16); - extra_text = "See the ordering information."; - MNU_MeasureString(extra_text, &w, &h); - MNU_DrawString(TEXT_XCENTER(w), 160, extra_text, 1, 16); - SET(item->flags, mf_disabled); - } - return TRUE; -} - -SWBOOL MNU_SaveGameCheck(MenuItem *item) -{ - extern SWBOOL InMenuLevel; - extern SWBOOL DemoMode; - - if (0) // JBF: Until we fix the symbol table dilemma, saving is off limits - { - SET(item->flags, mf_disabled); - return TRUE; - } - - if (CommEnabled || numplayers > 1 || DemoMode) - { - SET(item->flags, mf_disabled); - return TRUE; - } - - if (InMenuLevel) - SET(item->flags, mf_disabled); - else - { - if (TEST(Player[myconnectindex].Flags, PF_DEAD)) - SET(item->flags, mf_disabled); - else - RESET(item->flags, mf_disabled); - } - - - return TRUE; -} - -SWBOOL MNU_TenCheck(MenuItem *item) -{ - if (CommEnabled || numplayers > 1) - { - SET(item->flags, mf_disabled); - return TRUE; - } - - return TRUE; -} - -SWBOOL MNU_LoadGameCheck(MenuItem *item) -{ - - if (0) // JBF: Until we fix the symbol table dilemma, loading is off limits - { - SET(item->flags, mf_disabled); - return TRUE; - } - - if (CommEnabled || numplayers > 1) - { - SET(item->flags, mf_disabled); - return TRUE; - } - - return TRUE; -} - -SWBOOL MNU_StatCheck(MenuItem *item) -{ - if (CommEnabled || numplayers > 1) - { - SET(item->flags, mf_disabled); - return TRUE; - } - - return TRUE; -} - -SWBOOL MNU_HurtTeammateCheck(MenuItem *item) -{ - switch (gs.NetGameType+1) - { - // deathmatch and deathmatch no respawn - case MULTI_GAME_COMMBAT: - case MULTI_GAME_COMMBAT_NO_RESPAWN: - if (gs.NetTeamPlay) - RESET(item->flags, mf_disabled); - else - SET(item->flags, mf_disabled); - break; - // co-op - case MULTI_GAME_COOPERATIVE: - RESET(item->flags, mf_disabled); - break; - } - - return TRUE; -} - -SWBOOL MNU_TeamPlayCheck(MenuItem *item) -{ - switch (gs.NetGameType+1) - { - // co-op - case MULTI_GAME_COOPERATIVE: - SET(item->flags, mf_disabled); - break; - default: - RESET(item->flags, mf_disabled); - break; - } - - return TRUE; -} - -SWBOOL MNU_CoopPlayCheck(MenuItem *item) -{ - switch (gs.NetGameType+1) - { - // co-op - case MULTI_GAME_COOPERATIVE: - SET(item->flags, mf_disabled); - break; - default: - RESET(item->flags, mf_disabled); - break; - } - - return TRUE; -} - -SWBOOL -MNU_TeamPlayChange(void) -{ - // if team play changes then do a pre process again - MNU_ItemPreProcess(currentmenu); - return TRUE; -} - -SWBOOL MNU_MouseCheck(MenuItem *item) -{ - if (!CONTROL_MousePresent) - { - SET(item->flags, mf_disabled); - } - else - { - RESET(item->flags, mf_disabled); - } - - return TRUE; -} - -SWBOOL -MNU_JoystickCheck(MenuItem *item) -{ - if (!CONTROL_JoyPresent) - { - SET(item->flags, mf_disabled); - } - else - { - RESET(item->flags, mf_disabled); - } - - return TRUE; -} - -// This is only called when Enter is pressed -static SWBOOL -MNU_TryMusicInit(void) -{ - if (currentmenu->cursor == 0) - MNU_MusicCheck(¤tmenu->items[currentmenu->cursor+1]); - - return TRUE; -} - -SWBOOL -MNU_MusicCheck(MenuItem *item) -{ - RESET(item->flags, mf_disabled); - return TRUE; -} - -SWBOOL MNU_FxCheck(MenuItem *item) -{ - RESET(item->flags, mf_disabled); - return TRUE; -} - -SWBOOL MNU_MusicFxCheck(MenuItem *item) -{ - RESET(item->flags, mf_disabled); - return TRUE; -} - -//////////////////////////////////////////////// -// Do a toggle button -//////////////////////////////////////////////// -void MNU_DoButton(MenuItem_p item, SWBOOL draw) -{ - int x, y; - SWBOOL state; - int last_value; - short shade = MENU_SHADE_DEFAULT; - extern char LevelSong[]; - const char *extra_text = NULL; - PLAYERp pp = &Player[myconnectindex]; - int button_x,zero=0; - int handle=0; - extern SWBOOL MusicInitialized,FxInitialized; - - button_x = OPT_XSIDE; - - x = item->x; - y = item->y; - - if (TEST(item->flags, mf_disabled)) - { - shade = MENU_SHADE_INACTIVE; - } - - if (!draw) - { - switch (item->button) - { - case btn_nuke: - gs.NetNuke = state = buttonsettings[item->button]; - break; - case btn_voxels: - r_voxels = state = buttonsettings[item->button]; - break; - case btn_stats: - hud_stats = state = buttonsettings[item->button]; - break; - case btn_darts: - gs.Darts = state = buttonsettings[item->button]; - break; - case btn_autoswitch: - gs.WeaponAutoSwitch = state = buttonsettings[item->button]; - break; - case btn_markers: - gs.NetSpawnMarkers = state = buttonsettings[item->button]; - break; - case btn_teamplay: - gs.NetTeamPlay = state = buttonsettings[item->button]; - break; - case btn_friendlyfire: - gs.NetHurtTeammate = state = buttonsettings[item->button]; - break; - case btn_crosshair: - cl_crosshair = state = buttonsettings[item->button]; - break; - case btn_auto_aim: - last_value = cl_autoaim; - cl_autoaim = state = buttonsettings[item->button]; - if (cl_autoaim != last_value) - MenuButtonAutoAim = TRUE; - break; - case btn_messages: - hud_messages = state = buttonsettings[item->button]; - break; - case btn_auto_run: - last_value = cl_autorun; - cl_autorun = state = buttonsettings[item->button]; - if (cl_autorun != last_value) - MenuButtonAutoRun = TRUE; - break; - case btn_mouse_aim: - last_value = in_aimmode; - in_aimmode = state = buttonsettings[item->button]; - break; - case btn_mouse_invert: - in_mouseflip = state = buttonsettings[item->button]; - break; - case btn_bobbing: - cl_viewbob = state = buttonsettings[item->button]; - break; - case btn_sound: - - if (!FxInitialized) - break; - - last_value = snd_enabled; - snd_enabled = state = buttonsettings[item->button]; - if (snd_enabled != last_value) - { - if (!SoundEnabled()) - StopFX(); - } - break; - case btn_music: - last_value = mus_enabled; - mus_enabled = state = buttonsettings[item->button]; - if (mus_enabled != last_value) - { - SWBOOL bak; - - if (MusicEnabled()) - { - bak = DemoMode; - PlaySong(LevelSong, RedBookSong[Level], TRUE, TRUE); - DemoMode = bak; - } - else - { - bak = DemoMode; - StopSong(); - DemoMode = bak; - - if (SW_SHAREWARE) - { - handle = PlaySound(DIGI_NOLIKEMUSIC,&zero,&zero,&zero,v3df_none); - - if (handle > FX_Ok) - while (FX_SoundActive(handle)) - handleevents(); - } - } - } - break; - case btn_talking: - snd_speech = state = buttonsettings[item->button]; - break; - case btn_playcd: - last_value = true; - state = buttonsettings[item->button]; - break; - case btn_ambience: - last_value = snd_ambience; - snd_ambience = state = buttonsettings[item->button]; - if (snd_ambience != last_value) - { - if (!InMenuLevel) - { - if (snd_ambience) - StartAmbientSound(); - else - StopAmbientSound(); - } - } - break; - case btn_flipstereo: - last_value = snd_reversestereo; - snd_reversestereo = state = buttonsettings[item->button]; - break; - case btn_shadows: - r_shadows = state = buttonsettings[item->button]; - break; - - case btn_parental: - state = buttonsettings[btn_parental] = adult_lockout = FALSE; - if (!InMenuLevel) - JS_ToggleLockouts(); - break; - - case btn_videofs: - { - int lastx, lasty, lastbpp, newoffset, i; - - state = buttonsettings[btn_videofs]; - - lastx = validresolutions[slidersettings[sldr_videores]].xdim; - lasty = validresolutions[slidersettings[sldr_videores]].ydim; - lastbpp = validbpps[slidersettings[sldr_videobpp]]; - UpdateValidModes(lastbpp, buttonsettings[btn_videofs]); - - // check if the last bpp is still a valid choice - for (i=0; ibutton]; - break; - } - } - - if (!draw) - return; - - switch (item->button) - { - case btn_mouse_aim: - extra_text = in_aimmode ? "Momentary" : "Toggle"; - break; - default: break; - } - - - state = buttonsettings[item->button]; - - // Draw the button - if (item->text) - { - if (state) - { - // set - rotatesprite(button_x << 16, y << 16, MZ, 0, pic_radiobuttn2, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - } - else - { - // not set - rotatesprite(button_x << 16, y << 16, MZ, 0, pic_radiobuttn1, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - } - - MenuTextShade = shade; - MNU_DrawString(x, y, item->text, MenuTextShade, 16); - - if (extra_text) - MNU_DrawString(OPT_XSIDE + tilesiz[pic_radiobuttn1].x + 6, y, extra_text, MenuTextShade, 16); - MenuTextShade = MENU_SHADE_DEFAULT; - } - else - { - if (state) - rotatesprite(x << 16, y << 16, MZ, 0, pic_radiobuttn2, 2, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - else - rotatesprite(x << 16, y << 16, MZ, 0, pic_radiobuttn1, 2, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - - x += tilesiz[pic_radiobuttn1].x + 4; - - // Draw the menu item text - rotatesprite(x << 16, y << 16, MZ, 0, item->pic, 2, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - } - -} - -//char *gametype[] = {"War [Respawn]","Cooperative","War [No Respawn]"}; -const char *gametype[] = {"WangBang (spawn)","WangBang (no spawn)","Cooperative"}; -const char *playercolors[] = {"Brown","Gray","Purple","Red","Yellow","Olive","Green","Blue"}; -const char *monsterskills[] = {"No Monsters","Easy","Normal","Hard","Insane!"}; - -void -MNU_DoSlider(short dir, MenuItem_p item, SWBOOL draw) -{ - short offset, i, barwidth; - int x, y, knobx; - short shade = MENU_SHADE_DEFAULT; - const char *extra_text=NULL; - char tmp_text[256]; - - memset(tmp_text,0,256); - - if (TEST(item->flags, mf_disabled)) - { - shade = MENU_SHADE_INACTIVE; - dir = 0; - } - - switch (item->slider) - { - case sldr_mouse: - barwidth = SLDR_MOUSESENSEMAX; - offset = slidersettings[sldr_mouse] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_MOUSESENSEMAX-1)); - - slidersettings[sldr_mouse] = offset; - - in_mousesensitivity = float(offset * (MOUSE_SENS_MAX_VALUE/SLDR_MOUSESENSEMAX));// [JM] Will need to verify this. !CHECKME! - break; - - case sldr_sndfxvolume: - barwidth = SLDR_SNDFXVOLMAX; - offset = slidersettings[sldr_sndfxvolume] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_SNDFXVOLMAX-1)); - - slidersettings[sldr_sndfxvolume] = offset; - snd_fxvolume = FX_MIN + (offset * VOL_MUL); - FX_SetVolume(snd_fxvolume); - break; - - case sldr_musicvolume: - barwidth = SLDR_MUSICVOLMAX; - offset = slidersettings[sldr_musicvolume] += dir; - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_MUSICVOLMAX-1)); - - slidersettings[sldr_musicvolume] = offset; - mus_volume = MUSIC_MIN + (offset * VOL_MUL); - SetSongVolume(mus_volume); - break; - - case sldr_scrsize: - { - short bnum; - - barwidth = SLDR_SCRSIZEMAX; - slidersettings[sldr_scrsize] = gs.BorderNum; - slidersettings[sldr_scrsize] -= dir; - offset = slidersettings[sldr_scrsize]; - - if (TEST(item->flags, mf_disabled)) - break; - - ////DSPRINTF(ds,"BorderNum %d",gs.BorderNum); - //MONO_PRINT(ds); - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_SCRSIZEMAX - 1)); - - bnum = offset; - - offset = (SLDR_SCRSIZEMAX-1) - offset; - slidersettings[sldr_scrsize] = offset; - - if (!BorderAdjust) - gs.BorderNum = bnum; - - SetBorder(&Player[myconnectindex], bnum); - - break; - } - - case sldr_brightness: - barwidth = SLDR_BRIGHTNESSMAX; - offset = slidersettings[sldr_brightness] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_BRIGHTNESSMAX - 1)); - slidersettings[sldr_brightness] = offset; - - break; - - case sldr_bordertile: - barwidth = SLDR_BORDERTILEMAX; - offset = slidersettings[sldr_bordertile] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_BORDERTILEMAX - 1)); - slidersettings[sldr_bordertile] = offset; - - if (gs.BorderTile != offset) - { - gs.BorderTile = offset; - - SetRedrawScreen(&Player[myconnectindex]); - } - break; - - case sldr_gametype: - barwidth = SLDR_GAMETYPEMAX; - offset = slidersettings[sldr_gametype] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_GAMETYPEMAX - 1)); - slidersettings[sldr_gametype] = offset; - - extra_text = gametype[offset]; - MNU_DrawString(OPT_XSIDE, item->y, extra_text, 1, 16); - gs.NetGameType = offset; - // friendly fire menu - MNU_ItemPreProcess(currentmenu); - break; - - case sldr_netlevel: - barwidth = SLDR_NETLEVELMAX; - offset = slidersettings[sldr_netlevel] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_NETLEVELMAX - 1)); - slidersettings[sldr_netlevel] = offset; - - // Show the currently selected level on next line - //extra_text = MNU_LevelName[offset]; - //MNU_DrawString(OPT_XS, item->y+10, extra_text, 1, 16); - sprintf(tmp_text, "L%02d: %s", offset+1, LevelInfo[offset+1].Description); - MNU_DrawString(OPT_XS, item->y+10, tmp_text, 1, 16); - gs.NetLevel = offset; - break; - - case sldr_monsters: - barwidth = SLDR_MONSTERSMAX; - offset = slidersettings[sldr_monsters] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_MONSTERSMAX - 1)); - slidersettings[sldr_monsters] = offset; - - extra_text = monsterskills[offset]; - MNU_DrawString(OPT_XSIDE+54, item->y, extra_text, 1, 16); - gs.NetMonsters = offset; - break; - - case sldr_killlimit: - barwidth = SLDR_KILLLIMITMAX; - offset = slidersettings[sldr_killlimit] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_KILLLIMITMAX - 1)); - slidersettings[sldr_killlimit] = offset; - - if (offset == 0) - { - strcpy(tmp_text,"Infinite\n"); - } - else - { - sprintf(tmp_text,"%d",offset*10); - //itoa(offset*10,tmp_text,10); - } - MNU_DrawString(OPT_XSIDE+101, item->y, tmp_text, 1, 16); - gs.NetKillLimit = offset; - break; - - case sldr_timelimit: - barwidth = SLDR_TIMELIMITMAX; - offset = slidersettings[sldr_timelimit] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_TIMELIMITMAX - 1)); - slidersettings[sldr_timelimit] = offset; - - if (offset == 0) - { - strcpy(tmp_text,"Infinite\n"); - } - else - { - sprintf(tmp_text,"%d Minutes\n",TimeLimitTable[offset]); - } - - MNU_DrawString(OPT_XSIDE+86, item->y, tmp_text, 1, 16); - gs.NetTimeLimit = offset; - break; - - case sldr_playercolor: - barwidth = SLDR_PLAYERCOLORMAX; - offset = slidersettings[sldr_playercolor] += dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(SLDR_PLAYERCOLORMAX - 1)); - slidersettings[sldr_playercolor] = offset; - - extra_text = playercolors[offset]; - MNU_DrawString(OPT_XSIDE+78, item->y, extra_text, 1, PALETTE_PLAYER0+offset); - gs.NetColor = offset; - break; - - case sldr_videores: - { - offset = max(0,min(slidersettings[sldr_videores] + dir, numvalidresolutions-1)); - barwidth = numvalidresolutions; - - if (TEST(item->flags, mf_disabled)) - break; - - slidersettings[sldr_videores] = offset; - - sprintf(tmp_text, "%dx%d", validresolutions[offset].xdim, validresolutions[offset].ydim); - MNU_DrawString(OPT_XSIDE, item->y+OPT_YINC, tmp_text, 1, 16); - } break; - - case sldr_videobpp: - { - offset = max(0,min(slidersettings[sldr_videobpp] + dir, numvalidbpps-1)); - barwidth = numvalidbpps; - - if (TEST(item->flags, mf_disabled)) - break; - - if (slidersettings[sldr_videobpp] != offset) - { - int lastx, lasty, newoffset, i; - - slidersettings[sldr_videobpp] = offset; - - // find the nearest resolution to the one last selected - lastx = validresolutions[slidersettings[sldr_videores]].xdim; - lasty = validresolutions[slidersettings[sldr_videores]].ydim; - UpdateValidModes(validbpps[offset], buttonsettings[btn_videofs]); - newoffset = 0; - for (i=0; iy, tmp_text, 1, 16); - } break; - - case sldr_mousescalex: - case sldr_mousescaley: - barwidth = 8+1+8; - offset = slidersettings[item->slider] + dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(barwidth-1)); - - if (slidersettings[item->slider] != offset) - { - slidersettings[item->slider] = offset; - if (item->slider == sldr_mousescalex) in_mousescalex = offset<<13; - else in_mousescaley = offset<13; - } - - sprintf(tmp_text, "%.2f", (float)(slidersettings[item->slider]<<13) / 65535.f); - MNU_DrawSmallString(OPT_XSIDE+tilesiz[pic_slidelend].x+tilesiz[pic_sliderend].x+(MAX_SLDR_WIDTH+1)*tilesiz[pic_slidebar].x, item->y+4, tmp_text, 1, 16); - break; - - case sldr_joyaxisscale: - barwidth = 8+1+8; - offset = slidersettings[item->slider] + dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(barwidth-1)); - - if (slidersettings[item->slider] != offset) - { - slidersettings[item->slider] = offset; - //JoystickAnalogScale[JoystickAxisPage] = offset<<13; - CONTROL_SetAnalogAxisScale(JoystickAxisPage, offset<<13, controldevice_joystick); - } - - sprintf(tmp_text, "%.2f", (float)(slidersettings[item->slider]<<13) / 65535.f); - MNU_DrawSmallString(OPT_XSIDE+tilesiz[pic_slidelend].x+tilesiz[pic_sliderend].x+(MAX_SLDR_WIDTH+1)*tilesiz[pic_slidebar].x, item->y+4, tmp_text, 1, 16); - break; - - case sldr_joyaxisanalog: - { - const char *p; - - barwidth = MNU_ControlAxisOffset(analog_maxtype); - offset = slidersettings[item->slider] + dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(barwidth-1)); - - if (slidersettings[item->slider] != offset) - { - slidersettings[item->slider] = offset; - //JoystickAnalogAxes[JoystickAxisPage] = MNU_ControlAxisNum(offset); - CONTROL_MapAnalogAxis(JoystickAxisPage, MNU_ControlAxisNum(offset), controldevice_joystick); - } - - p = CONFIG_AnalogNumToName(MNU_ControlAxisNum(offset)); - while (*p != 0 && *p != '_') p++; - if (*p == '_') p++; - MNU_DrawSmallString(OPT_XSIDE+tilesiz[pic_slidelend].x+tilesiz[pic_sliderend].x+(barwidth+1)*tilesiz[pic_slidebar].x, item->y+4, p, 1, 16); - } - break; - - case sldr_joyaxisdead: - case sldr_joyaxissatur: - barwidth = (32768>>10)+1; - offset = slidersettings[item->slider] + dir; - - if (TEST(item->flags, mf_disabled)) - break; - - offset = max(offset, short(0)); - offset = min(offset, short(barwidth-1)); - - if (slidersettings[item->slider] != offset) - { - slidersettings[item->slider] = offset; - if (item->slider == sldr_joyaxisdead) - { - //JoystickAnalogDead[JoystickAxisPage] = min((offset<<10), 32767); - //CONTROL_SetJoyAxisDead(JoystickAxisPage, JoystickAnalogDead[JoystickAxisPage]); - } - else - { - //JoystickAnalogSaturate[JoystickAxisPage] = min((offset<<10), 32767); - //CONTROL_SetJoyAxisSaturate(JoystickAxisPage, JoystickAnalogSaturate[JoystickAxisPage]); - } - - //joySetDeadZone(JoystickAxisPage, JoystickAnalogDead[JoystickAxisPage], JoystickAnalogSaturate[JoystickAxisPage]); // [JM] !CHECKME! - } - - sprintf(tmp_text, "%.2f%%", (float)(slidersettings[item->slider]<<10) / 32767.f); - MNU_DrawSmallString(OPT_XSIDE+tilesiz[pic_slidelend].x+tilesiz[pic_sliderend].x+(MAX_SLDR_WIDTH+1)*tilesiz[pic_slidebar].x, item->y+4, tmp_text, 1, 16); - break; - - default: - return; - } - - if (!draw) - return; - - // Now draw it - item++; - x = item->x; - y = item->y; - - // Draw the left end cap of the bar - rotatesprite(x << 16, y << 16, MZ, 0, pic_slidelend, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - - x += tilesiz[pic_slidelend].x; - knobx = x; - - // Draw the in between sections - for (i = 0; i < min(barwidth, short(MAX_SLDR_WIDTH)); i++) - { - rotatesprite(x << 16, y << 16, MZ, 0, pic_slidebar, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - x += tilesiz[pic_slidebar].x; - } - - // Draw the right end cap - rotatesprite(x << 16, y << 16, MZ, 0, pic_sliderend, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - - // Draw the knob, compressing the X coordinate if the bar is too wide - if (barwidth > MAX_SLDR_WIDTH) - { - knobx += offset * (MAX_SLDR_WIDTH*tilesiz[pic_slidebar].x-tilesiz[pic_sliderknob].x) / (barwidth-1); - } - else - { - knobx += tilesiz[pic_slidebar].x * offset; - } - rotatesprite(knobx << 16, (y + 2) << 16, MZ, 0, pic_sliderknob, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); -} - -//////////////////////////////////////////////// -// Start up menu array -//////////////////////////////////////////////// -static void -MNU_SetupMenu(void) -{ - MenuGroup *rootmenu; - - static MenuGroup *rootmenulist[] = - { - &maingroup, - &SaveGameGroup, - &LoadGameGroup, - &soundgroup, - &optiongroup, - &quickloadgroup, - &quitgroup, - &ordergroup, - &episodegroup, - }; - - rootmenu = rootmenulist[ControlPanelType]; - ASSERT(ControlPanelType < ct_max); - - menuarrayptr = 0; - menuarray[0] = currentmenu = rootmenu; - if (ControlPanelType == ct_mainmenu) - - //order_input_buffered.button0 = order_input_buffered.button1 = FALSE; - //order_input_buffered.dir = dir_None; - ResetKeys(); - - // custom cust_callback starts out as null - cust_callback = NULL; - - // for QuitCustom and QuickLoadCustom - if (currentmenu->items == NULL) - { - if (currentmenu->draw_custom) - currentmenu->draw_custom(uc_setup, NULL); - } - - if (ControlPanelType == ct_mainmenu) - currentmenu->cursor = 0; - - // disable any items necessary - MNU_ItemPreProcess(currentmenu); -} - -//////////////////////////////////////////////// -// Draw an item -//////////////////////////////////////////////// -static void MNU_ClearFlags(MenuGroup * node) -{ - MenuItem *i; - - if (!node->items) - return; - - for (i = node->items; i->type != mt_none; i++) - { - i->flags &= ~MenuSelectFlags; - if (i->child) - MNU_ClearFlags((MenuGroup *) i->child); - } -} - -//////////////////////////////////////////////// -// Pop a group off the menu stack -//////////////////////////////////////////////// -static void MNU_PopGroup(void) -{ - if (!menuarrayptr) - return; - - currentmenu = menuarray[--menuarrayptr]; - - SetFragBar(Player + myconnectindex); - //PanelRefresh(Player + myconnectindex); -} - -//////////////////////////////////////////////// -// Push a group on to the menu stack -//////////////////////////////////////////////// -static void MNU_PushGroup(MenuGroup * node) -{ - if (menuarrayptr == MaxLayers - 1) - return; - - currentmenu = menuarray[++menuarrayptr] = node; - - SetFragBar(Player + myconnectindex); -} - -//////////////////////////////////////////////// -// Setup a new menu subgroup -//////////////////////////////////////////////// -static void MNU_SetupGroup(void) -{ - MNU_SelectItem(currentmenu, currentmenu->cursor, FALSE); - MNU_DrawMenu(); -} - -static VOID MNU_ItemPreProcess(MenuGroup * group) -{ - MenuItem *item; - - if (!group->items) - return; - - // process all items when going down a level - // to see if anything is disabled - for (item = group->items; item->type != mt_none; item++) - { - if (item->preprocess) - item->preprocess(item); - } -} - -void MNU_ItemPostProcess(MenuGroup *group) -{ - MenuItem *item; - int zero = 0; - - if (!group->items) - return; - - item = ¤tmenu->items[currentmenu->cursor]; - - if (item->postprocess) - { - item->postprocess(item); - } -} - -//////////////////////////////////////////////// -// Go to next menu subgroup -//////////////////////////////////////////////// -static void MNU_DownLevel(MenuGroup * group) -{ - - if (!group) - { - TerminateGame(); - printf("MNU_DownLevel() - NULL card\n"); - exit(0); - } - - MNU_PushGroup(group); - - if (group->items == NULL) - { - if (group->draw_custom && group->draw_custom(uc_setup, NULL)) - MNU_PopGroup(); - } - - MNU_ItemPreProcess(currentmenu); - - MNU_SetupGroup(); - - SetRedrawScreen(&Player[myconnectindex]); -} - -//////////////////////////////////////////////// -// Go to previous menu subgroup -//////////////////////////////////////////////// -static void MNU_UpLevel(void) -{ - int zero = 0; - static int handle1; - // if run out of menus then EXIT - if (!menuarrayptr) - { - if (!FX_SoundValidAndActive(handle1)) - handle1 = PlaySound(DIGI_STARCLINK,&zero,&zero,&zero,v3df_dontpan); - ExitMenus(); - return; - } - - if (currentmenu->items) - currentmenu->items[currentmenu->cursor].flags &= ~mf_selected; - MNU_PopGroup(); - MNU_SetupGroup(); - - SetRedrawScreen(&Player[myconnectindex]); -} - -//////////////////////////////////////////////// -// Do a menu item action -//////////////////////////////////////////////// - -static void MNU_DoItem(void) -{ - MenuItem *item; - - item = ¤tmenu->items[currentmenu->cursor]; - if (!item) return; - - if (TEST(item->flags, mf_disabled)) - { - // Try to process again - if (item->preprocess) - item->preprocess(item); - - // Check once more - if (TEST(item->flags, mf_disabled)) - return; - } - - switch (item->type) - { - case mt_option: - if (item->custom != NULL) - item->custom(); - break; - case mt_button: - MNU_PushItem(item, FALSE); - if (item->custom != NULL) - item->custom(); - break; - case mt_layer: - if (item->custom != NULL) - item->custom(); - MNU_DownLevel(item->child); - break; - default: break; - } -} - -//////////////////////////////////////////////// -// Draw an item icon or cursor -//////////////////////////////////////////////// -static void MNU_DrawItemIcon(MenuItem * item) -{ - //void BorderRefreshClip(PLAYERp pp, short x, short y, short x2, short y2); - int x = item->x, y = item->y; - int scale = MZ; - short w,h; - - if (item->text) - { - scale /= 2; - x -= mulscale17(tilesiz[pic_yinyang].x,scale) + 2; - y += 4; - } - else - { - scale -= (1<<13); - x -= ((tilesiz[pic_yinyang].x) / 2) - 3; - y += 8; - } - - rotatesprite(x << 16, y << 16, - scale, 0, pic_yinyang, item->shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - - SetRedrawScreen(&Player[myconnectindex]); - //BorderRefreshClip(&Player[myconnectindex], x - 24, y - 24, x + 24, y + 24); -} - -//////////////////////////////////////////////// -// Draw an item -//////////////////////////////////////////////// -static void MNU_DrawItem(MenuItem * item) -{ - char *ptr; - short px, py; - - MNU_ItemPostProcess(currentmenu); // Put this in so things can be drawn on item select - - if (!item->pic) - return; - - MNU_DrawItemIcon(item); - - // if text string skip this part - if (item->text) - return; - - if (TEST(item->flags, mf_selected) && !TEST(item->flags, mf_disabled)) - { - // Highlighted - if (item->type != mt_button) - rotatesprite(item->x << 16, item->y << 16, MZ, 0, item->pic, - -30 + STD_RANDOM_RANGE(50), PALETTE_MENU_HIGHLIGHT, MenuDrawFlags, - 0, 0, xdim - 1, ydim - 1); - else - rotatesprite((item->x + tilesiz[pic_radiobuttn1].x + 4) << 16, item->y << 16, - MZ, 0, item->pic, item->shade, PALETTE_MENU_HIGHLIGHT, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - } - else - { - // Un highlighted - if (item->type != mt_button) - rotatesprite(item->x << 16, item->y << 16, MZ, 0, item->pic, - item->shade, 0, MenuDrawFlags, 0, 319, 199, 0); - else - rotatesprite((item->x + tilesiz[pic_radiobuttn1].x + 4) << 16, item->y << 16, - MZ, 0, item->pic, item->shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - } -} - -//////////////////////////////////////////////// -// Draw the menu contents -//////////////////////////////////////////////// -static void MNU_DrawMenuContents(void) -{ - MenuItem *item; - short w,h; - - ASSERT(currentmenu != NULL); - - if (currentmenu->text) - { - // Draw the backdrop bar - rotatesprite(10 << 16, (currentmenu->y-3) << 16, MZ, 0, 2427, - currentmenu->shade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); - MNU_MeasureStringLarge(currentmenu->text, &w, &h); - MNU_DrawString(TEXT_XCENTER(w), currentmenu->y, currentmenu->text, 1, 16); - } - else if (currentmenu->titlepic) - { - rotatesprite(currentmenu->x << 16, currentmenu->y << 16, MZ, 0, currentmenu->titlepic, - currentmenu->shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - } - - if (!currentmenu->items) - return; - - for (item = currentmenu->items; item->type != mt_none; item++) - { - if (item->pic) - { - if (item->type == mt_button) - { - // all drawing done here also - MNU_DoButton(item, TRUE); - } - else - { - if (item->text) - { - if (TEST(item->flags, mf_disabled)) - MenuTextShade = MENU_SHADE_INACTIVE; - MNU_DrawString(item->x, item->y, item->text, MenuTextShade, 16); - MenuTextShade = MENU_SHADE_DEFAULT; - } - else - { - rotatesprite(item->x << 16, item->y << 16, MZ, 0, item->pic, - item->shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1); - } - } - } - - // Is there a slider attached to this item? Draw it. - if (item->type == mt_slider) - MNU_DoSlider(0, item, TRUE); - } - - MNU_SelectItem(currentmenu, currentmenu->cursor, TRUE); - - if (currentmenu->draw_custom) - currentmenu->draw_custom(uc_touchup, NULL); -} - -//////////////////////////////////////////////// -// Draw the menu -//////////////////////////////////////////////// -void MNU_DrawMenu(void) -{ - if (cust_callback != NULL) - { - cust_callback(cust_callback_call, cust_callback_item); - return; - } - - if (currentmenu->items || currentmenu->titlepic) - { - MNU_DrawMenuContents(); - } -} - -//////////////////////////////////////////////// -// Select a menu item -//////////////////////////////////////////////// -void MNU_SelectItem(MenuGroup * group, short index, SWBOOL draw) -{ - MenuItem *item; - - if (index != group->cursor) - { - item = &group->items[group->cursor]; - item->flags &= ~mf_selected; - if (draw) - MNU_DrawItem(item); - } - - group->cursor = index; - item = &group->items[group->cursor]; - - item->flags |= mf_selected; - if (draw) - MNU_DrawItem(item); -} - -//////////////////////////////////////////////// -// Toggle a menu radio button on/off -//////////////////////////////////////////////// -static void MNU_PushItem(MenuItem * item, SWBOOL draw) -{ - if (item->type != mt_button) - return; - - buttonsettings[item->button] ^= 1; - -// if (draw) - MNU_DoButton(item, draw); -} - -//////////////////////////////////////////////// -// Go to next item on menu -//////////////////////////////////////////////// -static void MNU_NextItem(void) -{ - MenuTag type; - MenuFlags flag; - - type = currentmenu->items[currentmenu->cursor + 1].type; - flag = currentmenu->items[currentmenu->cursor + 1].flags; - - if (type == mt_none) - MNU_SelectItem(currentmenu, 0, FALSE); - else - MNU_SelectItem(currentmenu, currentmenu->cursor + 1, FALSE); - - type = currentmenu->items[currentmenu->cursor].type; - flag = currentmenu->items[currentmenu->cursor].flags; - - if (type == mt_inert || flag == mf_disabled) - MNU_NextItem(); -} - -//////////////////////////////////////////////// -// Go to previous item on menu -//////////////////////////////////////////////// -static void MNU_PrevItem(void) -{ - MenuTag type; - MenuFlags flag; - - if (!currentmenu->cursor) - while (currentmenu->items[++currentmenu->cursor].type != mt_none) ; - - MNU_SelectItem(currentmenu, currentmenu->cursor - 1, FALSE); - - type = currentmenu->items[currentmenu->cursor].type; - flag = currentmenu->items[currentmenu->cursor].flags; - if (type == mt_inert || flag == mf_disabled) - MNU_PrevItem(); -} - -//////////////////////////////////////////////// -// Find hotkey press on current menu, if any. -//////////////////////////////////////////////// -static SWBOOL MNU_DoHotkey(void) -{ - MenuItem_p item; - short index; - - if (!currentmenu->items) return FALSE; - - index = 0; - for (item = currentmenu->items; item->type != mt_none; item++) - { - if (inputState.GetKeyStatus(item->hotkey) && item->hotkey != 0) - { - MNU_SelectItem(currentmenu, index, FALSE); - return TRUE; - } - index++; - } - - return FALSE; -} - -//////////////////////////////////////////////// -// Setup Menus -//////////////////////////////////////////////// -void SetupMenu(void) -{ - if (!UsingMenus && !ConPanel) // Doing this check for multiplay - // menus - { - MNU_SetupMenu(); - - // Clear the previous ESC key press - inputState.ClearKeyStatus(sc_Escape); - UsingMenus = TRUE; - } -} - -//////////////////////////////////////////////// -// Setup the main menu -// This function will not loop if in modem -// or network game, otherwise it stops the -// game play until user finished in menus. -//////////////////////////////////////////////// -#define MNU_SENSITIVITY 10 // The menu's mouse sensitivity, should be real low - -void MNU_DoMenu( CTLType type, PLAYERp pp ) -{ - SWBOOL resetitem; - unsigned char key; - int zero = 0; - static int handle2; - static int limitmove=0; - static SWBOOL select_held=FALSE; - - resetitem = TRUE; - - if (cust_callback != NULL) - { - cust_callback(cust_callback_call, cust_callback_item); - return; - } - - //ControlPanelType = type; - SetupMenu(); - - // should not get input if you are editing a save game slot - if (totalclock < limitmove) limitmove = (int32_t) totalclock; - - if (I_MenuUp()) - { - I_MenuUpClear(); - MNU_PrevItem(); - resetitem = TRUE; - } - else if (I_MenuDown()) - { - I_MenuDownClear(); - MNU_NextItem(); - resetitem = TRUE; - } - else if (I_GeneralTrigger()) - { - static int handle5=0; - I_GeneralTriggerClear(); - if (!FX_SoundValidAndActive(handle5)) - handle5 = PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan); - inputState.ClearKeysDown(); - MNU_DoItem(); - resetitem = TRUE; - } - else if (I_MenuLeft() - && currentmenu->items[currentmenu->cursor].type == mt_slider) - { - I_MenuLeftClear(); - MNU_DoSlider(-1, ¤tmenu->items[currentmenu->cursor], FALSE); - resetitem = TRUE; - } - else if (I_MenuRight() - && currentmenu->items[currentmenu->cursor].type == mt_slider) - { - I_MenuRightClear(); - MNU_DoSlider(1, ¤tmenu->items[currentmenu->cursor], FALSE); - resetitem = TRUE; - } - else if (I_ReturnTrigger()) - { - I_ReturnTriggerClear(); - static int handle3; - if (!FX_SoundValidAndActive(handle3)) - handle3 = PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan); - MNU_UpLevel(); - resetitem = TRUE; - } - else if (MNU_DoHotkey()) - { - static int handle4; - if (!FX_SoundValidAndActive(handle4)) - handle4 = PlaySound(DIGI_STAR,&zero,&zero,&zero,v3df_dontpan); - resetitem = TRUE; - } - else - resetitem = FALSE; - - // !FRANK! I added this because the old custom was only called for drawing - // Needed one for drawing and moving. - if (currentmenu->move_custom) - currentmenu->move_custom(uc_setup, NULL); - - if (resetitem) - { - inputState.ClearKeysDown(); - ResetKeys(); - } -} - -//////////////////////////////////////////////// -// Checks to see if we should be in menus -//////////////////////////////////////////////// -void MNU_CheckForMenus(void) -{ - extern SWBOOL GamePaused; - - if (UsingMenus) - { - //if (MoveSkip2 == 0) - MNU_DoMenu(ct_mainmenu, Player + myconnectindex); - } - else - { - if ((inputState.GetKeyStatus(KEYSC_ESC)) && dimensionmode == 3 && !ConPanel) - { - inputState.ClearKeyStatus(sc_Escape); - inputState.ClearKeysDown(); - // setup sliders/buttons - MNU_InitMenus(); - MNU_DoMenu(ct_mainmenu, Player + myconnectindex); - pMenuClearTextLine(Player + myconnectindex); - PauseGame(); - } - } -} - -void MNU_CheckForMenusAnyKey(void) -{ - if (UsingMenus) - { - //if (MoveSkip2 == 0) - MNU_DoMenu(ct_mainmenu, Player + myconnectindex); - } - else - { - if (KeyPressed()) - { - ResetKeys(); - inputState.ClearKeysDown(); - MNU_InitMenus(); - MNU_DoMenu(ct_mainmenu, Player + myconnectindex); - pMenuClearTextLine(Player + myconnectindex); - } - } -} - -static int MNU_ControlAxisOffset(int num) -{ - switch (num) - { - case analog_turning: return 0; - case analog_strafing: return 1; - case analog_moving: return 2; - case analog_lookingupanddown: return 3; - case analog_maxtype: return 4; - default: return 0; - } -} - -static int MNU_ControlAxisNum(int offset) -{ - switch (offset) - { - case 0: return analog_turning; - case 1: return analog_strafing; - case 2: return analog_moving; - case 3: return analog_lookingupanddown; - default: return analog_turning; - } -} - - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Miscellaneous Routines -/////////////////////////////////////////////////////////////////////////////////////////////////// - -typedef struct RGB_color_typ -{ - unsigned char red; - unsigned char green; - unsigned char blue; -} RGB_color, *RGB_color_ptr; - -#define PALETTE_MASK 0x3c6 -#define PALETTE_READ 0x3c7 -#define PALETTE_WRITE 0x3c8 -#define PALETTE_DATA 0x3c9 - -unsigned char palette_data[256][3]; // Global palette array - -// V E R T I C A L R E T R A C E V A R I A B L E S ////////////////////////////////////////// - -#define VGA_INPUT_STATUS_1 0x3DA // VGA status register 1, bit 3 is the vid_vsync -// 1 = retrace in progress -// 0 = no retrace -#define VGA_VSYNC_MASK 0x08 // Masks off unwanted bits of status register. - - -// These routines are not used and should not be used. Would interfere with VESA palette -// cards. -#if 0 -///////////////////////////////////////////////// -// WaitForVsync -// Waits for a vertical retrace to occur. If one is in progress, it waits for the next one. -///////////////////////////////////////////////// -void WaitForVsync(void) -{ - while (inp(VGA_INPUT_STATUS_1) & VGA_VSYNC_MASK) ; - // Retrace in progress, wait. - - // Wait for vid_vsync, and exit. - while (!inp(VGA_INPUT_STATUS_1) & VGA_VSYNC_MASK) ; -} - -void Get_Palette(unsigned char *pal) -{ - int i; - - outp(PALETTE_READ, 0); - for (i = 0; i < 768; i++) - pal[i] = inp(PALETTE_DATA); -} - -void Set_Palette(unsigned char *buff) -{ - int i; - - outp(PALETTE_WRITE, 0); // Resets color ram pointer to 1st - // color - for (i = 0; i < 768; i++) - outp(PALETTE_DATA, buff[i]); -} - -#endif - - -/* -================================================================================================= -= -= FadeOut - Fades the palette to color at assigned click rate -= -================================================================================================= -*/ -// Heres some temp timer junk for this routine. Replace it with game timer stuff later. -//unsigned int *clock = (unsigned int *)0x046C; - -void Fade_Timer(int clicks) -{ -// unsigned int now; - int now; - - now = (int32_t) totalclock; - - while (abs((int32_t) totalclock - now) < clicks) handleevents(); -} - -void FadeIn(unsigned char startcolor, unsigned int clicks) -{ - int i, palreg, usereg, tmpreg1 = 0, tmpreg2 = 0; - RGB_color color; - unsigned char temp_pal[768], *palette; - - if (videoGetRenderMode() >= REND_POLYMOST) return; - - palette = &palette_data[0][0]; - - color.red = palette_data[startcolor][0]; - color.green = palette_data[startcolor][1]; - color.blue = palette_data[startcolor][2]; - - usereg = 0; - for (i = 0; i < 768; i++) - { - if (usereg == 0) - temp_pal[i] = color.red; - else if (usereg == 1) - temp_pal[i] = color.green; - else - temp_pal[i] = color.blue; - - if (++usereg > 2) - usereg = 0; - } - - for (i = 0; i < 32; i++) - { - for (palreg = 0; palreg < 768; palreg++) - { - tmpreg1 = (int)(temp_pal[palreg]) + 2; - tmpreg2 = (int)(temp_pal[palreg]) - 2; - if (tmpreg1 > 255) - tmpreg1 = 255; - if (tmpreg2 < 0) - tmpreg2 = 0; - - if (temp_pal[palreg] < palette[palreg]) - { - if ((temp_pal[palreg] = tmpreg1) > palette[palreg]) - temp_pal[palreg] = palette[palreg]; - } - else if (temp_pal[palreg] > palette[palreg]) - if ((temp_pal[palreg] = tmpreg2) < palette[palreg]) - temp_pal[palreg] = palette[palreg]; - - } - - set_pal(&temp_pal[0]); - - // Delay clicks - Fade_Timer(clicks); - } -} - -void FadeOut(unsigned char targetcolor, unsigned int clicks) -{ - int i, palreg, usereg = 0, tmpreg1 = 0, tmpreg2 = 0; - RGB_color color; - unsigned char temp_pal[768]; - - if (videoGetRenderMode() >= REND_POLYMOST) return; - - color.red = palette_data[targetcolor][0]; - color.green = palette_data[targetcolor][1]; - color.blue = palette_data[targetcolor][2]; - - memcpy(&temp_pal[0], &palette_data[0][0], 768); - - for (i = 0; i < 32; i++) - { - for (palreg = 0; palreg < 768; palreg++) - { - tmpreg1 = (int)(temp_pal[palreg]) + 2; - tmpreg2 = (int)(temp_pal[palreg]) - 2; - if (tmpreg1 > 255) - tmpreg1 = 255; - if (tmpreg2 < 0) - tmpreg2 = 0; - - if (usereg == 0) - { - if (temp_pal[palreg] < color.red) - { - if ((temp_pal[palreg] = tmpreg1) > color.red) - temp_pal[palreg] = color.red; - } - else if (temp_pal[palreg] > color.red) - if ((temp_pal[palreg] = tmpreg2) < color.red) - temp_pal[palreg] = color.red; - } - else if (usereg == 1) - { - if (temp_pal[palreg] < color.green) - { - if ((temp_pal[palreg] = tmpreg1) > color.green) - temp_pal[palreg] = color.green; - } - else if (temp_pal[palreg] > color.green) - if ((temp_pal[palreg] = tmpreg2) < color.green) - temp_pal[palreg] = color.green; - } - else if (usereg == 2) - { - if (temp_pal[palreg] < color.blue) - { - if ((temp_pal[palreg] = tmpreg1) > color.blue) - temp_pal[palreg] = color.blue; - } - else if (temp_pal[palreg] > color.blue) - if ((temp_pal[palreg] = tmpreg2) < color.blue) - temp_pal[palreg] = color.blue; - } - - if (++usereg > 2) - usereg = 0; - } - - - set_pal(&temp_pal[0]); - - // Delay clicks - Fade_Timer(clicks); - } -} ////////////////////////////////////////////////////////////////////////////// #define FADE_DAMAGE_FACTOR 3 // 100 health / 32 shade cycles = 3.125 @@ -4484,7 +402,16 @@ static int faderamp[32] = 96,80,64,48,32,16 }; + +typedef struct RGB_color_typ +{ + unsigned char red; + unsigned char green; + unsigned char blue; +} RGB_color, * RGB_color_ptr; + unsigned char ppalette[MAX_SW_PLAYERS_REG][768]; +unsigned char palette_data[256][3]; // Global palette array ////////////////////////////////////////// // Set the amount of redness for damage @@ -4493,10 +420,10 @@ unsigned char ppalette[MAX_SW_PLAYERS_REG][768]; void SetFadeAmt(PLAYERp pp, short damage, unsigned char startcolor) { int palreg, usereg = 0, tmpreg1 = 0, tmpreg2 = 0; - short fadedamage=0; + short fadedamage = 0; RGB_color color; - //CON_ConMessage("SetAmt: fadeamt = %d, startcolor = %d, pp = %d",pp->FadeAmt,startcolor,pp->StartColor); + //OSD_Printf("SetAmt: fadeamt = %d, startcolor = %d, pp = %d",pp->FadeAmt,startcolor,pp->StartColor); if (abs(pp->FadeAmt) > 0 && startcolor == pp->StartColor) return; @@ -4508,14 +435,14 @@ void SetFadeAmt(PLAYERp pp, short damage, unsigned char startcolor) // Reset the palette if (pp == Player + screenpeek) { - videoFadePalette(0,0,0,0); + videoFadePalette(0, 0, 0, 0); if (pp->FadeAmt <= 0) GetPaletteFromVESA(&ppalette[screenpeek][0]); } if (damage < -150 && damage > -1000) fadedamage = 150; else if (damage < -1000) // Underwater - fadedamage = abs(damage+1000); + fadedamage = abs(damage + 1000); else fadedamage = abs(damage); @@ -4599,7 +526,7 @@ void SetFadeAmt(PLAYERp pp, short damage, unsigned char startcolor) if (pp == Player + screenpeek) { if (videoGetRenderMode() < REND_POLYMOST) set_pal(pp->temp_pal); - else videoFadePalette(color.red, color.green, color.blue, faderamp[min(31,max(0,32-abs(pp->FadeAmt)))]); + else videoFadePalette(color.red, color.green, color.blue, faderamp[min(31, max(0, 32 - abs(pp->FadeAmt)))]); if (damage < -1000) pp->FadeAmt = 1000; // Don't call DoPaletteFlash for underwater stuff } @@ -4612,7 +539,7 @@ void SetFadeAmt(PLAYERp pp, short damage, unsigned char startcolor) void DoPaletteFlash(PLAYERp pp) { int i, palreg, tmpreg1 = 0, tmpreg2 = 0; - unsigned char *pal_ptr = &ppalette[screenpeek][0]; + unsigned char* pal_ptr = &ppalette[screenpeek][0]; if (pp->FadeAmt <= 1) @@ -4621,7 +548,7 @@ void DoPaletteFlash(PLAYERp pp) pp->StartColor = 0; if (pp == Player + screenpeek) { - videoFadePalette(0,0,0,0); + videoFadePalette(0, 0, 0, 0); memcpy(pp->temp_pal, palette_data, sizeof(palette_data)); DoPlayerDivePalette(pp); // Check Dive again DoPlayerNightVisionPalette(pp); // Check Night Vision again @@ -4657,7 +584,7 @@ void DoPaletteFlash(PLAYERp pp) pp->StartColor = 0; if (pp == Player + screenpeek) { - videoFadePalette(0,0,0,0); + videoFadePalette(0, 0, 0, 0); memcpy(pp->temp_pal, palette_data, sizeof(palette_data)); DoPlayerDivePalette(pp); // Check Dive again DoPlayerNightVisionPalette(pp); // Check Night Vision again @@ -4697,7 +624,7 @@ void DoPaletteFlash(PLAYERp pp) palette_data[pp->StartColor][0], palette_data[pp->StartColor][1], palette_data[pp->StartColor][2], - faderamp[min(31,max(0,32-abs(pp->FadeAmt)))] + faderamp[min(31, max(0, 32 - abs(pp->FadeAmt)))] ); } } @@ -4706,18 +633,39 @@ void DoPaletteFlash(PLAYERp pp) } -void ResetPalette(PLAYERp pp) + +SWBOOL MNU_ShareWareMessage() { - videoFadePalette(0,0,0,0); - memcpy(pp->temp_pal, palette_data, sizeof(palette_data)); - //DoPlayerDivePalette(pp); // Check Dive again - //DoPlayerNightVisionPalette(pp); // Check Night Vision again - pp->FadeAmt = 0; - pp->StartColor = 0; - pp->FadeTics = 0; + const char* extra_text; + short w, h; + + if (SW_SHAREWARE) + { + extra_text = "Be sure to call 800-3DREALMS today"; + MNU_MeasureString(extra_text, &w, &h); + MNU_DrawString(TEXT_XCENTER(w), 110, extra_text, 1, 16); + extra_text = "and order the game."; + MNU_MeasureString(extra_text, &w, &h); + MNU_DrawString(TEXT_XCENTER(w), 120, extra_text, 1, 16); + extra_text = "You are only playing the first "; + MNU_MeasureString(extra_text, &w, &h); + MNU_DrawString(TEXT_XCENTER(w), 130, extra_text, 1, 16); + extra_text = "four levels, and are missing most"; + MNU_MeasureString(extra_text, &w, &h); + MNU_DrawString(TEXT_XCENTER(w), 140, extra_text, 1, 16); + extra_text = "of the game, weapons and monsters."; + MNU_MeasureString(extra_text, &w, &h); + MNU_DrawString(TEXT_XCENTER(w), 150, extra_text, 1, 16); + extra_text = "See the ordering information."; + MNU_MeasureString(extra_text, &w, &h); + MNU_DrawString(TEXT_XCENTER(w), 160, extra_text, 1, 16); + //SET(item->flags, mf_disabled); + } + return TRUE; } -// vim:ts=4:sw=4:enc=utf-8: +#if 0 +#endif END_SW_NS diff --git a/source/sw/src/menus.h b/source/sw/src/menus.h index bf707d95e..6a1289569 100644 --- a/source/sw/src/menus.h +++ b/source/sw/src/menus.h @@ -32,73 +32,12 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms BEGIN_SW_NS -#define MENU_SHADE_DEFAULT 0 -#define MENU_SHADE_INACTIVE 20 - -typedef enum -{ - ct_mainmenu, ct_savemenu, ct_loadmenu, ct_soundmenu, ct_optionmenu, ct_quickloadmenu, - ct_quitmenu, ct_ordermenu, ct_episodemenu, ct_max -} CTLType; - -extern SWBOOL UsingMenus; -extern int SENSITIVITY; -extern CTLType ControlPanelType; -extern int16_t MenuTextShade; -extern int16_t MenuTextPalette; - -// Prototypes -//void MNU_DoMenu( CTLType type, PLAYERp pp ); -void MNU_InitMenus(void); -//void (*CustomRefresh)(void); -//void MNU_Refresh( void ); -void MNU_DrawMenu(void); // This is used in drawscreen to refresh menus in -// multiplay situations. -void MNU_CheckForMenus(void); -void MNU_CheckForMenusAnyKey(void); -void MNU_MeasureString(const char *string, short *w, short *h); -void MNU_DrawString(short x, short y, const char *string, short shade, short pal); -void MNU_MeasureSmallString(const char *string,short *w,short *h); -void MNU_DrawSmallString(short x,short y,const char *string,short shade,short pal); -void MNU_MeasureStringLarge(const char *string, short *w, short *h); -void MNU_DrawStringLarge(short x, short y, const char *string); - -// Functions from my other engine -//void Get_Palette (unsigned char *pal); -//void Set_Palette(unsigned char *buff); -//void Fade_Timer(int clicks); -void FadeIn(unsigned char targetcolor, unsigned int clicks); -void FadeOut(unsigned char targetcolor, unsigned int clicks); -void ResetPalette(PLAYERp pp); - -void ExitMenus(void); -void ResetMenuInput(void); - -extern SWBOOL BorderAdjust; -extern SWBOOL MultiPlayQuitFlag; - -// Make memcpy an intrinsic function for an easy frame rate boost -//#pragma intrinsic( memcpy ); - -// L O C A L V A R I A B L E S //////////////////////////////////////////////////////////////// - -// Default menu pic brightness -#define m_defshade 2 - -#define FLASHTIME 60 // One second per icon flash - -// Defines for permanentwritesprite clipping box -#define M_CX1 0 -#define M_CY1 0 -#define M_CX2 319 -#define M_CY2 199 - -#define MZ 65536 - -#define asc_Esc 27 -#define asc_Enter 13 -#define asc_Space 32 - +void MNU_MeasureString(const char* string, short* w, short* h); +void MNU_DrawString(short x, short y, const char* string, short shade, short pal); +void MNU_MeasureSmallString(const char* string, short* w, short* h); +void MNU_DrawSmallString(short x, short y, const char* string, short shade, short pal); +void MNU_MeasureStringLarge(const char* string, short* w, short* h); +void MNU_DrawStringLarge(short x, short y, const char* string, int shade = 0); #define pic_none 0 #define pic_radiobuttn1 2816 @@ -152,6 +91,68 @@ extern SWBOOL MultiPlayQuitFlag; #define pic_savedescr 2924 #define pic_shadow_warrior 2366 +#define m_defshade 2 +#define MenuDrawFlags (ROTATE_SPRITE_SCREEN_CLIP) +extern SWBOOL LoadGameOutsideMoveLoop; + + +#if 0 + +typedef enum +{ + ct_mainmenu, ct_savemenu, ct_loadmenu, ct_soundmenu, ct_optionmenu, ct_quickloadmenu, + ct_quitmenu, ct_ordermenu, ct_episodemenu, ct_max +} CTLType; + +extern int SENSITIVITY; +extern CTLType ControlPanelType; +extern int16_t MenuTextShade; +extern int16_t MenuTextPalette; + +// Prototypes +//void MNU_DoMenu( CTLType type, PLAYERp pp ); +void MNU_InitMenus(void); +//void (*CustomRefresh)(void); +//void MNU_Refresh( void ); +void MNU_DrawMenu(void); // This is used in drawscreen to refresh menus in +// multiplay situations. +void MNU_CheckForMenus(void); +void MNU_CheckForMenusAnyKey(void); + +// Functions from my other engine +//void Get_Palette (unsigned char *pal); +//void Set_Palette(unsigned char *buff); +//void Fade_Timer(int clicks); +void FadeIn(unsigned char targetcolor, unsigned int clicks); +void FadeOut(unsigned char targetcolor, unsigned int clicks); +void ResetPalette(PLAYERp pp); + +void ExitMenus(void); +void ResetMenuInput(void); + +extern SWBOOL BorderAdjust; + +// Make memcpy an intrinsic function for an easy frame rate boost +//#pragma intrinsic( memcpy ); + +// L O C A L V A R I A B L E S //////////////////////////////////////////////////////////////// + +// Default menu pic brightness + +#define FLASHTIME 60 // One second per icon flash + +// Defines for permanentwritesprite clipping box +#define M_CX1 0 +#define M_CY1 0 +#define M_CX2 319 +#define M_CY2 199 + +#define asc_Esc 27 +#define asc_Enter 13 +#define asc_Space 32 + + + // This is the current values set with all slider bar functions #define SENSE_DEFAULT 10 // Default mouse sensitivity ** should be 5!!! #define FXVOL_DEFAULT 8 // Default sound fx volume @@ -228,7 +229,6 @@ enum typedef int MenuFlags; #define MenuSelectFlags (mf_pushed | mf_selected | mf_disabled) -#define MenuDrawFlags (ROTATE_SPRITE_SCREEN_CLIP) typedef enum { @@ -284,7 +284,6 @@ typedef struct MenuGroup // Custom Routine Prototypes //////////////////////////////////////////////////////////////////// SWBOOL MNU_QuitCustom(UserCall call, MenuItem *item); -SWBOOL MNU_QuickLoadCustom(UserCall call, MenuItem *item); SWBOOL MNU_LoadSaveTouchupCustom(UserCall call, MenuItem *item); SWBOOL MNU_OrderCustom(UserCall call, MenuItem *item); SWBOOL MNU_DoEpisodeSelect(UserCall call, MenuItem *item); @@ -336,6 +335,8 @@ typedef struct int x,y; } VMODE; +#endif + END_SW_NS #endif diff --git a/source/sw/src/mfile.h b/source/sw/src/mfile.h index 4702e170c..6ee541090 100644 --- a/source/sw/src/mfile.h +++ b/source/sw/src/mfile.h @@ -26,19 +26,31 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "compat.h" #include "cache1d.h" +#include "savegamehelp.h" BEGIN_SW_NS -typedef FILE* MFILE_WRITE; -typedef FILE* MFILE_READ; +typedef FileWriter* MFILE_WRITE; +typedef FileReader* MFILE_READ; + +inline size_t MREAD(void* buf, size_t size, size_t nelem, FileReader* handle) +{ + return handle->Read(buf, size * nelem) / size; +} + +inline size_t MWRITE(void* buf, size_t size, size_t nelem, FileWriter* handle) +{ + return handle->Write(buf, size * nelem) / size; +} + +inline void MCLOSE_WRITE(FileWriter* handle) +{ + FinishSavegameWrite(); +} + +inline void MCLOSE_READ(FileReader* handle) +{ + FinishSavegameRead(); +} -// This needs some real fixing... -#define MREAD(ptr, size, num,handle) fread((ptr),(size),(num),(handle)) -#define MWRITE(ptr, size, num,handle) fwrite((ptr),(size),(num),(handle)) -#define MOPEN_WRITE(name) fopen(name,"wb") -#define MOPEN_READ(name) fopen(name,"rb") -#define MCLOSE_WRITE(handle) fclose(handle) -#define MCLOSE_READ(handle) fclose(handle) -#define MOPEN_WRITE_ERR nullptr -#define MOPEN_READ_ERR nullptr END_SW_NS diff --git a/source/sw/src/miscactr.cpp b/source/sw/src/miscactr.cpp index ab0d0369b..f6cb36992 100644 --- a/source/sw/src/miscactr.cpp +++ b/source/sw/src/miscactr.cpp @@ -838,7 +838,7 @@ int PachinkoCheckWin(short SpriteNum) u->WaitTics = 0; // Can operate it again now - //CON_ConMessage("bool1 = %d",TEST_BOOL1(sp)); + //OSD_Printf("bool1 = %d",TEST_BOOL1(sp)); // You already won, no more from this machine! if (TEST_BOOL1(sp)) return 0; diff --git a/source/sw/src/network.cpp b/source/sw/src/network.cpp index 1eb21c93f..d4c5db866 100644 --- a/source/sw/src/network.cpp +++ b/source/sw/src/network.cpp @@ -631,7 +631,7 @@ waitforeverybody(void) handleevents(); getpackets(); - if (quitevent || (wfe_ExitCallback && wfe_ExitCallback())) + if (wfe_ExitCallback && wfe_ExitCallback()) { // allow exit //if (inputState.GetKeyStatus(KEYSC_ESC)) @@ -1497,7 +1497,6 @@ getpackets(void) NewGame = TRUE; // restart demo for multi-play mode DemoInitOnce = FALSE; - ResetMenuInput(); // send a dummy packet to see when it arrives //tempbuf[0] = PACKET_TYPE_DUMMY; diff --git a/source/sw/src/network.h b/source/sw/src/network.h index 8e9f175df..141eb4fbb 100644 --- a/source/sw/src/network.h +++ b/source/sw/src/network.h @@ -1,3 +1,4 @@ +#pragma once //------------------------------------------------------------------------- /* Copyright (C) 1997, 2005 - 3D Realms Entertainment diff --git a/source/sw/src/panel.cpp b/source/sw/src/panel.cpp index 21b0defb9..378896da2 100644 --- a/source/sw/src/panel.cpp +++ b/source/sw/src/panel.cpp @@ -44,6 +44,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "weapon.h" #include "fx_man.h" +#include "menu/menu.h" +#include "swcvar.h" BEGIN_SW_NS @@ -67,7 +69,6 @@ int InitFistAttack(PLAYERp pp); //#define UK_VERSION TRUE #define PANF_UZI_XFLIP (BIT(21)) -extern SWBOOL UsingMenus; #define XDIM 320 #define YDIM 200 @@ -775,7 +776,7 @@ void PlayerUpdatePanelInfo(PLAYERp pp) if (Prediction) return; - if (UsingMenus) + if (M_Active()) return; PlayerUpdateHealth(pp, 0); @@ -1822,7 +1823,7 @@ InitWeaponStar(PLAYERp pp) PlaySound(DIGI_PULL, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); if (STD_RANDOM_RANGE(1000) > 900 && pp == Player+myconnectindex) { - if (!gs.Darts) + if (!sw_darts) PlayerSound(DIGI_ILIKESHURIKEN,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); } @@ -7347,7 +7348,6 @@ pDisplaySprites(PLAYERp pp) int smoothratio; unsigned i; - SECT_USERp sectu = SectUser[pp->cursectnum]; uint8_t pal = 0; short ang; int flags; @@ -7389,7 +7389,7 @@ pDisplaySprites(PLAYERp pp) picnum = psp->picndx; // UK panzies have to have darts instead of shurikens. - if (gs.Darts) + if (sw_darts) switch (picnum) { case STAR_REST: @@ -7453,7 +7453,7 @@ pDisplaySprites(PLAYERp pp) case STAR_REST: case 2510: - if (!gs.Darts) + if (!sw_darts) picnum = 2138; else picnum = 2518; // Bloody Dart Hand @@ -7488,17 +7488,23 @@ pDisplaySprites(PLAYERp pp) // if its a weapon sprite and the view is set to the outside don't draw the sprite if (TEST(psp->flags, PANF_WEAPON_SPRITE)) { - pal = sector[pp->cursectnum].floorpal; - - if (sector[pp->cursectnum].floorpal != PALETTE_DEFAULT) + SECT_USERp sectu = nullptr; + int16_t floorshade = 0; + if (pp->cursectnum >= 0) { - SECT_USERp sectu = SectUser[pp->cursectnum]; - if (sectu && TEST(sectu->flags, SECTFU_DONT_COPY_PALETTE)) - pal = PALETTE_DEFAULT; - } + sectu = SectUser[pp->cursectnum]; + pal = sector[pp->cursectnum].floorpal; + floorshade = sector[pp->cursectnum].floorshade; - if (pal == PALETTE_FOG || pal == PALETTE_DIVE || pal == PALETTE_DIVE_LAVA) - pal = psp->pal; // Set it back + if (pal != PALETTE_DEFAULT) + { + if (sectu && TEST(sectu->flags, SECTFU_DONT_COPY_PALETTE)) + pal = PALETTE_DEFAULT; + } + + if (pal == PALETTE_FOG || pal == PALETTE_DIVE || pal == PALETTE_DIVE_LAVA) + pal = psp->pal; // Set it back + } /////////// @@ -7508,7 +7514,7 @@ pDisplaySprites(PLAYERp pp) } //shade = overlay_shade = DIV2(sector[pp->cursectnum].floorshade + sector[pp->cursectnum].ceilingshade); - shade = overlay_shade = sector[pp->cursectnum].floorshade - 10; + shade = overlay_shade = floorshade - 10; if (TEST(psp->PlayerP->Flags, PF_VIEW_FROM_OUTSIDE)) { @@ -7592,7 +7598,7 @@ pDisplaySprites(PLAYERp pp) } #if 1 - if (TEST(psp->flags, PANF_KILL_AFTER_SHOW) && !TEST(psp->flags, PANF_NOT_ALL_PAGES)) + if (TEST(psp->flags, PANF_KILL_AFTER_SHOW) && !TEST(psp->flags, PANF_NOT_ALL_PAGES) && !M_Active()) { psp->numpages = 0; SET(flags, ROTATE_SPRITE_ALL_PAGES); @@ -7666,7 +7672,7 @@ pSpriteControl(PLAYERp pp) // RULE: Sprites can only kill themselves PRODUCTION_ASSERT(psp); ASSERT(ValidPtr(psp)); - ASSERT((uint32_t) psp->Next != 0xCCCCCCCC); + // ASSERT((uint32_t) psp->Next != 0xCCCCCCCC); if (psp->State) pStateControl(psp); diff --git a/source/sw/src/player.cpp b/source/sw/src/player.cpp index 79a4f332a..f320a223a 100644 --- a/source/sw/src/player.cpp +++ b/source/sw/src/player.cpp @@ -65,6 +65,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "vis.h" #include "track.h" #include "interp.h" +#include "menu/menu.h" +#include "gstrings.h" BEGIN_SW_NS @@ -1794,13 +1796,14 @@ DoPlayerTurnTurret(PLAYERp pp) void SlipSlope(PLAYERp pp) { - short wallptr = sector[pp->cursectnum].wallptr; short ang; - SECT_USERp sectu = SectUser[pp->cursectnum]; + SECT_USERp sectu; - if (!sectu || !TEST(sectu->flags, SECTFU_SLIDE_SECTOR) || !TEST(sector[pp->cursectnum].floorstat, FLOOR_STAT_SLOPE)) + if (pp->cursectnum < 0 || !(sectu = SectUser[pp->cursectnum]) || !TEST(sectu->flags, SECTFU_SLIDE_SECTOR) || !TEST(sector[pp->cursectnum].floorstat, FLOOR_STAT_SLOPE)) return; + short wallptr = sector[pp->cursectnum].wallptr; + ang = getangle(wall[wall[wallptr].point2].x - wall[wallptr].x, wall[wall[wallptr].point2].y - wall[wallptr].y); ang = NORM_ANGLE(ang + 512); @@ -1818,7 +1821,7 @@ PlayerAutoLook(PLAYERp pp) if (!TEST(pp->Flags, PF_FLYING|PF_SWIMMING|PF_DIVING|PF_CLIMBING|PF_JUMPING|PF_FALLING)) { - if (!g_MyAimMode && TEST(sector[pp->cursectnum].floorstat, FLOOR_STAT_SLOPE)) // If the floor is sloped + if (!TEST(pp->Flags, PF_MOUSE_AIMING_ON) && TEST(sector[pp->cursectnum].floorstat, FLOOR_STAT_SLOPE)) // If the floor is sloped { // Get a point, 512 units ahead of player's position x = pp->posx + (sintable[(pp->pang + 512) & 2047] >> 5); @@ -2414,7 +2417,7 @@ MoveScrollMode2D(PLAYERp pp) mfsvel = mfvel = 0; - if (MenuInputMode || UsingMenus) + if (M_Active()) return; // Recenter view if told @@ -2476,7 +2479,7 @@ MoveScrollMode2D(PLAYERp pp) } } - if (!UsingMenus && !HelpInputMode && !ConPanel) + if (!HelpInputMode && !ConPanel) { if (buttonMap.ButtonDown(gamefunc_Move_Forward)) { @@ -2520,23 +2523,13 @@ MoveScrollMode2D(PLAYERp pp) void DoPlayerMenuKeys(PLAYERp pp) { - if (!CommEnabled) - { - if (TEST_SYNC_KEY((pp), SK_AUTO_AIM)) - { - if (FLAG_KEY_PRESSED(pp, SK_AUTO_AIM)) - { - FLAG_KEY_RELEASE(pp, SK_AUTO_AIM); - FLIP(pp->Flags, PF_AUTO_AIM); - } - } - else - FLAG_KEY_RESET(pp, SK_AUTO_AIM); - } } void PlayerSectorBound(PLAYERp pp, int amt) { + if (pp->cursectnum < 9) + return; + int cz,fz; // player should never go into a sector @@ -2680,7 +2673,7 @@ DoPlayerMove(PLAYERp pp) DoPlayerHorizon(pp); - if (TEST(sector[pp->cursectnum].extra, SECTFX_DYNAMIC_AREA)) + if (pp->cursectnum >= 0 && TEST(sector[pp->cursectnum].extra, SECTFX_DYNAMIC_AREA)) { if (TEST(pp->Flags, PF_FLYING|PF_JUMPING|PF_FALLING)) { @@ -2722,6 +2715,9 @@ DoPlayerSectorUpdatePreMove(PLAYERp pp) { short sectnum = pp->cursectnum; + if (sectnum < 0) + return; + if (TEST(sector[pp->cursectnum].extra, SECTFX_DYNAMIC_AREA)) { updatesectorz(pp->posx, pp->posy, pp->posz, §num); @@ -2749,13 +2745,12 @@ DoPlayerSectorUpdatePreMove(PLAYERp pp) void DoPlayerSectorUpdatePostMove(PLAYERp pp) { - short sectnum; + short sectnum = pp->cursectnum; int fz,cz; // need to do updatesectorz if in connect area - if (FAF_ConnectArea(pp->cursectnum)) + if (sectnum >= 0 && FAF_ConnectArea(sectnum)) { - sectnum = pp->cursectnum; updatesectorz(pp->posx, pp->posy, pp->posz, &pp->cursectnum); // can mess up if below @@ -2773,7 +2768,7 @@ DoPlayerSectorUpdatePostMove(PLAYERp pp) // try again updatesectorz(pp->posx, pp->posy, pp->posz, &pp->cursectnum); - ASSERT(pp->cursectnum >= 0); + // ASSERT(pp->cursectnum >= 0); } } else @@ -3641,7 +3636,7 @@ void StackedWaterSplash(PLAYERp pp) updatesectorz(pp->posx, pp->posy, SPRITEp_BOS(pp->SpriteP), §num); - if (SectorIsUnderwaterArea(sectnum)) + if (sectnum >= 0 && SectorIsUnderwaterArea(sectnum)) { PlaySound(DIGI_SPLASH1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); } @@ -3662,7 +3657,7 @@ DoPlayerFall(PLAYERp pp) FLAG_KEY_RESET(pp, SK_JUMP); } - if (SectorIsUnderwaterArea(pp->cursectnum)) + if (pp->cursectnum >= 0 && SectorIsUnderwaterArea(pp->cursectnum)) { StackedWaterSplash(pp); DoPlayerBeginDiveNoWarp(pp); @@ -4094,7 +4089,7 @@ DoPlayerWadeSuperJump(PLAYERp pp) { hitinfo.sect = wall[hitinfo.wall].nextsector; - if (labs(sector[hitinfo.sect].floorz - pp->posz) < Z(50)) + if (hitinfo.sect >= 0 && labs(sector[hitinfo.sect].floorz - pp->posz) < Z(50)) { if (Distance(pp->posx, pp->posy, hitinfo.pos.x, hitinfo.pos.y) < ((((int)pp->SpriteP->clipdist)<<2) + 256)) return TRUE; @@ -4245,7 +4240,7 @@ DoPlayerCrawl(PLAYERp pp) { USERp u = User[pp->PlayerSprite]; - if (SectorIsUnderwaterArea(pp->cursectnum)) + if (pp->cursectnum >= 0 && SectorIsUnderwaterArea(pp->cursectnum)) { // if stacked water - which it should be if (FAF_ConnectArea(pp->cursectnum)) @@ -4348,7 +4343,7 @@ DoPlayerCrawl(PLAYERp pp) return; } - if (TEST(sector[pp->cursectnum].extra, SECTFX_DYNAMIC_AREA)) + if (pp->cursectnum >= 0 && TEST(sector[pp->cursectnum].extra, SECTFX_DYNAMIC_AREA)) { pp->posz = pp->loz - PLAYER_CRAWL_HEIGHT; } @@ -4430,7 +4425,7 @@ DoPlayerFly(PLAYERp pp) { USERp u = User[pp->PlayerSprite]; - if (SectorIsUnderwaterArea(pp->cursectnum)) + if (pp->cursectnum >= 0 && SectorIsUnderwaterArea(pp->cursectnum)) { DoPlayerBeginDiveNoWarp(pp); return; @@ -4694,7 +4689,7 @@ PlayerCanDiveNoWarp(PLAYERp pp) updatesectorz(pp->posx, pp->posy, SPRITEp_BOS(pp->SpriteP), §num); - if (SectorIsUnderwaterArea(sectnum)) + if (sectnum >= 0 && SectorIsUnderwaterArea(sectnum)) { pp->cursectnum = sectnum; pp->posz = sector[sectnum].ceilingz; @@ -5116,7 +5111,7 @@ void DoPlayerBeginDiveNoWarp(PLAYERp pp) if (Prediction) return; - if (!SectorIsUnderwaterArea(pp->cursectnum)) + if (pp->cursectnum < 0 || !SectorIsUnderwaterArea(pp->cursectnum)) return; if (pp->Bloody) pp->Bloody = FALSE; // Water washes away the blood @@ -5282,7 +5277,7 @@ DoPlayerDive(PLAYERp pp) SECT_USERp sectu = SectUser[pp->cursectnum]; // whenever your view is not in a water area - if (!SectorIsUnderwaterArea(pp->cursectnum)) + if (pp->cursectnum < 0 || !SectorIsUnderwaterArea(pp->cursectnum)) { DoPlayerStopDiveNoWarp(pp); DoPlayerBeginRun(pp); @@ -6475,7 +6470,6 @@ DoPlayerBeginDie(PLAYERp pp) short bak; int choosesnd = 0; extern short GlobInfoStringTime; - extern short QuickLoadNum; USERp u = User[pp->PlayerSprite]; @@ -6518,15 +6512,17 @@ DoPlayerBeginDie(PLAYERp pp) PlayerSound(PlayerLowHealthPainVocs[choosesnd],&pp->posx, &pp->posy,&pp->posy,v3df_dontpan|v3df_doppler|v3df_follow,pp); +#if 0 if (!CommEnabled && numplayers <= 1 && QuickLoadNum >= 0) { ReloadPrompt = TRUE; } else +#endif { bak = GlobInfoStringTime; GlobInfoStringTime = 999; - PutStringInfo(pp, "Press SPACE to restart"); + PutStringInfo(pp, GStrings("TXT_PRESSSPACER")); GlobInfoStringTime = bak; } @@ -7356,7 +7352,7 @@ DoPlayerRun(PLAYERp pp) { USERp u = User[pp->PlayerSprite]; - if (SectorIsUnderwaterArea(pp->cursectnum)) + if (pp->cursectnum >= 0 && SectorIsUnderwaterArea(pp->cursectnum)) { DoPlayerBeginDiveNoWarp(pp); return; @@ -7428,7 +7424,7 @@ DoPlayerRun(PLAYERp pp) { if (TEST_SYNC_KEY(pp, SK_OPERATE)) { - if (FLAG_KEY_PRESSED(pp, SK_OPERATE)) + if (FLAG_KEY_PRESSED(pp, SK_OPERATE) && pp->cursectnum >= 0) { if (TEST(sector[pp->cursectnum].extra, SECTFX_OPERATIONAL)) { @@ -7659,7 +7655,7 @@ void ChopsCheck(PLAYERp pp) extern SWBOOL HelpInputMode; extern int ChopTics; - if (!UsingMenus && !HelpInputMode && !TEST(pp->Flags, PF_DEAD) && !pp->sop_riding && numplayers <= 1) + if (!M_Active() && !HelpInputMode && !TEST(pp->Flags, PF_DEAD) && !pp->sop_riding && numplayers <= 1) { if ((pp->input.bits|pp->input.vel|pp->input.svel|pp->input.angvel|pp->input.aimvel) || TEST(pp->Flags, PF_CLIMBING|PF_FALLING|PF_DIVING)) @@ -7885,11 +7881,11 @@ void PauseMultiPlay(void) if (GamePaused) { short w,h; -#define MSG_GAME_PAUSED "Game Paused" - MNU_MeasureString(MSG_GAME_PAUSED, &w, &h); + auto m = GStrings("Game Paused"); + MNU_MeasureString(m, &w, &h); TRAVERSE_CONNECT(p) - PutStringTimer(Player + p, TEXT_TEST_COL(w), 100, MSG_GAME_PAUSED, 999); + PutStringTimer(Player + p, TEXT_TEST_COL(w), 100, m, 999); SavePrediction = PredictionOn; PredictionOn = FALSE; @@ -8405,6 +8401,9 @@ DoFootPrints(short SpriteNum) if (u->PlayerP) { + if (u->PlayerP->cursectnum < 0) + return 0; + if (FAF_ConnectArea(u->PlayerP->cursectnum)) return 0; diff --git a/source/sw/src/rooms.cpp b/source/sw/src/rooms.cpp index 92a258c6f..bf3befdfe 100644 --- a/source/sw/src/rooms.cpp +++ b/source/sw/src/rooms.cpp @@ -59,7 +59,7 @@ SWBOOL FAF_DebugView = 0; void COVERupdatesector(int32_t x, int32_t y, int16_t* newsector) { - ASSERT(*newsector>=0 && *newsector=0 && *newsector= 0 && secte >= 0); + // ASSERT(sects >= 0 && secte >= 0); // early out to regular routine - if (!FAF_Sector(sects) && !FAF_Sector(secte)) + if ((sects < 0 || !FAF_Sector(sects)) && (secte < 0 || !FAF_Sector(secte))) { return cansee(xs,ys,zs,sects,xe,ye,ze,secte); } @@ -356,7 +356,7 @@ GetZadjustment(short sectnum, short hitag) short i, nexti; SPRITEp sp; - if (!TEST(sector[sectnum].extra, SECTFX_Z_ADJUST)) + if (sectnum < 0 || !TEST(sector[sectnum].extra, SECTFX_Z_ADJUST)) return 0L; TRAVERSE_SPRITE_STAT(headspritestat[STAT_ST1], i, nexti) @@ -517,7 +517,7 @@ void FAFgetzrange(int32_t x, int32_t y, int32_t z, int16_t sectnum, // because the ceiling and floors get moved out of the way for drawing. // early out to regular routine - if (!FAF_ConnectArea(sectnum)) + if (sectnum < 0 || !FAF_ConnectArea(sectnum)) { getzrange_old(x, y, z, sectnum, hiz, ceilhit, loz, florhit, clipdist, clipmask); SectorZadjust(*ceilhit, hiz, *florhit, loz); @@ -545,7 +545,7 @@ void FAFgetzrange(int32_t x, int32_t y, int32_t z, int16_t sectnum, updatesectorz(x, y, newz, &uppersect); if (uppersect < 0) - _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d", x, y, newz); + return; // _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d", x, y, newz); getzrange_old(x, y, newz, uppersect, hiz, ceilhit, &foo1, &foo2, clipdist, clipmask); SectorZadjust(*ceilhit, hiz, -1, NULL); } @@ -568,7 +568,7 @@ void FAFgetzrange(int32_t x, int32_t y, int32_t z, int16_t sectnum, updatesectorz(x, y, newz, &lowersect); if (lowersect < 0) - _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d", x, y, newz); + return; // _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d", x, y, newz); getzrange_old(x, y, newz, lowersect, &foo1, &foo2, loz, florhit, clipdist, clipmask); SectorZadjust(-1, NULL, *florhit, loz); WaterAdjust(*florhit, loz); @@ -614,7 +614,7 @@ void FAFgetzrangepoint(int32_t x, int32_t y, int32_t z, int16_t sectnum, } updatesectorz(x, y, newz, &uppersect); if (uppersect < 0) - _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d, sectnum %d", x, y, newz, sectnum); + return; // _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d, sectnum %d", x, y, newz, sectnum); getzrangepoint(x, y, newz, uppersect, hiz, ceilhit, &foo1, &foo2); SectorZadjust(*ceilhit, hiz, -1, NULL); } @@ -630,7 +630,7 @@ void FAFgetzrangepoint(int32_t x, int32_t y, int32_t z, int16_t sectnum, } updatesectorz(x, y, newz, &lowersect); if (lowersect < 0) - _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d, sectnum %d", x, y, newz, sectnum); + return; // _ErrMsg(ERR_STD_ARG, "Did not find a sector at %d, %d, %d, sectnum %d", x, y, newz, sectnum); getzrangepoint(x, y, newz, lowersect, &foo1, &foo2, loz, florhit); SectorZadjust(-1, NULL, *florhit, loz); WaterAdjust(*florhit, loz); diff --git a/source/sw/src/rotator.cpp b/source/sw/src/rotator.cpp index 97cd46f1d..dcf0d2a3c 100644 --- a/source/sw/src/rotator.cpp +++ b/source/sw/src/rotator.cpp @@ -35,6 +35,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "text.h" #include "interp.h" #include "sprite.h" +#include "quotemgr.h" BEGIN_SW_NS @@ -180,7 +181,7 @@ DoRotatorMatch(PLAYERp pp, short match, SWBOOL manual) // SWBOOL 8 must be set for message to display if (TEST_BOOL4(fsp) && (gNet.MultiGameType == MULTI_GAME_COMMBAT || gNet.MultiGameType == MULTI_GAME_AI_BOTS)) { - if (pp && TEST_BOOL11(fsp)) PutStringInfo(pp,"This only opens in single play."); + if (pp && TEST_BOOL11(fsp)) PutStringInfo(pp, GStrings("TXT_SPONLY")); continue; } @@ -217,7 +218,7 @@ DoRotatorMatch(PLAYERp pp, short match, SWBOOL manual) else #endif { - PutStringInfo(pp, KeyDoorMessage[key_num - 1]); + PutStringInfo(pp, quoteMgr.GetExQuote(QUOTE_DOORMSG + key_num - 1)); return -1; } } diff --git a/source/sw/src/save.cpp b/source/sw/src/save.cpp index 7aafcf519..d4ec3501f 100644 --- a/source/sw/src/save.cpp +++ b/source/sw/src/save.cpp @@ -56,6 +56,9 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "colormap.h" #include "player.h" #include "i_specialpaths.h" +#include "savegamehelp.h" +#include "z_music.h" +#include "mapinfo.h" //void TimerFunc(task * Task); BEGIN_SW_NS @@ -72,9 +75,7 @@ TO DO */ extern int lastUpdate; -extern uint8_t RedBookSong[40]; extern char UserMapName[80]; -extern char LevelSong[16]; extern char SaveGameDescr[10][80]; extern int PlayClock; extern short TotalKillable; @@ -220,7 +221,8 @@ int LoadSymCodeInfo(MFILE_READ fil, void **ptr) } -int SaveGame(short save_num) + +bool GameInterface::SaveGame(FSaveGameNode *sv) { MFILE_WRITE fil; int i,j; @@ -240,20 +242,20 @@ int SaveGame(short save_num) PANEL_SPRITE tpanel_sprite; PANEL_SPRITEp psp,cur,next; SECTOR_OBJECTp sop; - char game_name[256]; int cnt = 0, saveisshot=0; OrgTileP otp, next_otp; Saveable_Init(); - - snprintf(game_name, 256, "%sgame%d.sav", M_GetSavegamesPath().GetChars(), save_num); - if ((fil = MOPEN_WRITE(game_name)) == MOPEN_WRITE_ERR) - return -1; + + + auto game_name = G_BuildSaveName(sv->Filename); + OpenSaveGameForWrite(game_name); + // workaround until the level info here has been transitioned. + G_WriteSaveHeader(sv->SaveTitle); + fil = WriteSavegameChunk("snapshot.sw"); MWRITE(&GameVersion,sizeof(GameVersion),1,fil); - MWRITE(SaveGameDescr[save_num],sizeof(SaveGameDescr[save_num]),1,fil); - MWRITE(&Level,sizeof(Level),1,fil); MWRITE(&Skill,sizeof(Skill),1,fil); @@ -662,8 +664,6 @@ int SaveGame(short save_num) // game settings MWRITE(&gNet,sizeof(gNet),1,fil); - MWRITE(LevelSong,sizeof(LevelSong),1,fil); - MWRITE(palette,sizeof(palette),1,fil); MWRITE(palette_data,sizeof(palette_data),1,fil); MWRITE(&gs,sizeof(gs),1,fil); @@ -690,72 +690,17 @@ int SaveGame(short save_num) //MWRITE(&Zombies, sizeof(Zombies), 1, fil); MCLOSE_WRITE(fil); + if (!saveisshot) + return FinishSavegameWrite(); - ////DSPRINTF(ds, "done saving"); - //MONO_PRINT(ds); - - if (saveisshot) - CON_Message("There was a problem saving. See \"Save Help\" section of release notes."); - - return saveisshot ? -1 : 0; -} - -int LoadGameFullHeader(short save_num, char *descr, short *level, short *skill) -{ - MFILE_READ fil; - char game_name[256]; - short tile; - int ver; - - snprintf(game_name, 256, "%sgame%d.sav", M_GetSavegamesPath().GetChars(), save_num); - if ((fil = MOPEN_READ(game_name)) == MOPEN_READ_ERR) - return -1; - - MREAD(&ver,sizeof(ver),1,fil); - if (ver != GameVersion) - { - MCLOSE_READ(fil); - return -1; - } - - MREAD(descr, sizeof(SaveGameDescr[0]), 1,fil); - - MREAD(level,sizeof(*level),1,fil); - MREAD(skill,sizeof(*skill),1,fil); - - tile = ScreenLoadSaveSetup(Player + myconnectindex); - ScreenLoad(fil); - - MCLOSE_READ(fil); - - return tile; -} - -void LoadGameDescr(short save_num, char *descr) -{ - MFILE_READ fil; - char game_name[256]; - short tile; - int ver; - - snprintf(game_name, 256, "%sgame%d.sav", M_GetSavegamesPath().GetChars(), save_num); - if ((fil = MOPEN_READ(game_name)) == MOPEN_READ_ERR) - return; - - MREAD(&ver,sizeof(ver),1,fil); - if (ver != GameVersion) - { - MCLOSE_READ(fil); - return; - } - - MREAD(descr, sizeof(SaveGameDescr[0]),1,fil); - - MCLOSE_READ(fil); + return false; } -int LoadGame(short save_num) +extern SWBOOL LoadGameOutsideMoveLoop; +extern SWBOOL InMenuLevel; + +bool GameInterface::LoadGame(FSaveGameNode* sv) { MFILE_READ fil; int i,j,saveisshot=0; @@ -771,39 +716,40 @@ int LoadGame(short save_num) int16_t data_ndx; PANEL_SPRITEp psp,next,cur; PANEL_SPRITE tpanel_sprite; - char game_name[256]; OrgTileP otp, next_otp; int RotNdx; int StateStartNdx; int StateNdx; int StateEndNdx; - extern SWBOOL InMenuLevel; + + if (!InMenuLevel) PauseAction(); Saveable_Init(); - snprintf(game_name, 256, "%sgame%d.sav", M_GetSavegamesPath().GetChars(), save_num); - if ((fil = MOPEN_READ(game_name)) == MOPEN_READ_ERR) - return -1; + auto game_name = G_BuildSaveName(sv->Filename); + OpenSaveGameForRead(game_name); + + auto filr = ReadSavegameChunk("snapshot.sw"); + if (!filr.isOpen()) return false; + fil = &filr; MREAD(&i,sizeof(i),1,fil); if (i != GameVersion) { MCLOSE_READ(fil); - return -1; + return false; } // Don't terminate until you've made sure conditions are valid for loading. if (InMenuLevel) - StopSong(); + Mus_Stop(); else TerminateLevel(); Terminate3DSounds(); Terminate3DSounds(); - MREAD(SaveGameDescr[save_num], sizeof(SaveGameDescr[save_num]),1,fil); - MREAD(&Level,sizeof(Level),1,fil); MREAD(&Skill,sizeof(Skill),1,fil); @@ -843,7 +789,7 @@ int LoadGame(short save_num) saveisshot |= LoadSymCodeInfo(fil, (void **)&pp->DoPlayerAction); saveisshot |= LoadSymDataInfo(fil, (void **)&pp->sop_control); saveisshot |= LoadSymDataInfo(fil, (void **)&pp->sop_riding); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } } @@ -875,12 +821,12 @@ int LoadGame(short save_num) saveisshot |= LoadSymDataInfo(fil, (void **)&psp->ActionState); saveisshot |= LoadSymDataInfo(fil, (void **)&psp->RestState); saveisshot |= LoadSymCodeInfo(fil, (void **)&psp->PanelSpriteFunc); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } for (j = 0; j < (int)SIZ(psp->over); j++) { saveisshot |= LoadSymDataInfo(fil, (void **)&psp->over[j].State); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } } } @@ -970,7 +916,7 @@ int LoadGame(short save_num) saveisshot |= LoadSymDataInfo(fil, (void **)&u->SpriteP); saveisshot |= LoadSymDataInfo(fil, (void **)&u->PlayerP); saveisshot |= LoadSymDataInfo(fil, (void **)&u->tgt_sp); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } MREAD(&SpriteNum,sizeof(SpriteNum),1,fil); } @@ -986,7 +932,7 @@ int LoadGame(short save_num) saveisshot |= LoadSymCodeInfo(fil, (void **)&sop->Animator); saveisshot |= LoadSymDataInfo(fil, (void **)&sop->controller); saveisshot |= LoadSymDataInfo(fil, (void **)&sop->sp_child); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } } MREAD(SineWaveFloor, sizeof(SineWaveFloor),1,fil); @@ -1059,7 +1005,7 @@ int LoadGame(short save_num) saveisshot |= LoadSymCodeInfo(fil, (void **)&a->callback); saveisshot |= LoadSymDataInfo(fil, (void **)&a->callbackdata); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } } #else AnimCnt = 0; @@ -1079,7 +1025,7 @@ int LoadGame(short save_num) saveisshot |= LoadSymDataInfo(fil, (void **)&a->ptr); saveisshot |= LoadSymCodeInfo(fil, (void **)&a->callback); saveisshot |= LoadSymDataInfo(fil, (void **)&a->callbackdata); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } } #endif #endif @@ -1108,7 +1054,7 @@ int LoadGame(short save_num) MREAD(bakipos,sizeof(bakipos),1,fil); for (i = numinterpolations - 1; i >= 0; i--) saveisshot |= LoadSymDataInfo(fil, (void **)&curipos[i]); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } // short interpolations MREAD(&short_numinterpolations,sizeof(short_numinterpolations),1,fil); @@ -1117,7 +1063,7 @@ int LoadGame(short save_num) MREAD(short_bakipos,sizeof(short_bakipos),1,fil); for (i = short_numinterpolations - 1; i >= 0; i--) saveisshot |= LoadSymDataInfo(fil, (void **)&short_curipos[i]); - if (saveisshot) { MCLOSE_READ(fil); return -1; } + if (saveisshot) { MCLOSE_READ(fil); return false; } // parental lock for (i = 0; i < (int)SIZ(otlist); i++) @@ -1165,8 +1111,6 @@ int LoadGame(short save_num) // game settings MREAD(&gNet,sizeof(gNet),1,fil); - MREAD(LevelSong,sizeof(LevelSong),1,fil); - MREAD(palette,sizeof(palette),1,fil); MREAD(palette_data,sizeof(palette_data),1,fil); @@ -1278,11 +1222,10 @@ int LoadGame(short save_num) screenpeek = myconnectindex; PlayingLevel = Level; - PlaySong(LevelSong, RedBookSong[Level], TRUE, TRUE); + MUS_ResumeSaved(); if (snd_ambience) StartAmbientSound(); FX_SetVolume(snd_fxvolume); - SetSongVolume(mus_volume); TRAVERSE_CONNECT(i) { @@ -1299,7 +1242,12 @@ int LoadGame(short save_num) DoPlayerDivePalette(Player+myconnectindex); DoPlayerNightVisionPalette(Player+myconnectindex); - return 0; + + ExitLevel = TRUE; + LoadGameOutsideMoveLoop = TRUE; + + if (!InMenuLevel) ready2send = 1; + return true; } void diff --git a/source/sw/src/scrip2.cpp b/source/sw/src/scrip2.cpp index aa770c3c2..c98ce0b2c 100644 --- a/source/sw/src/scrip2.cpp +++ b/source/sw/src/scrip2.cpp @@ -39,6 +39,9 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "jsector.h" #include "parent.h" #include "scriptfile.h" +#include "menu/menu.h" +#include "quotemgr.h" +#include "mapinfo.h" BEGIN_SW_NS @@ -81,7 +84,7 @@ SWBOOL LoadScriptFile(const char *filename) - if (!(fp = kopenFileReader(filename, 0)).isOpen()) + if (!(fp = fileSystem.OpenFileReader(filename, 0)).isOpen()) { // If there's no script file, forget it. return FALSE; @@ -89,7 +92,7 @@ SWBOOL LoadScriptFile(const char *filename) size = fp.GetLength(); - scriptbuffer = (char *)AllocMem(size); + scriptbuffer = (char *)AllocMem(size+1); ASSERT(scriptbuffer != NULL); @@ -97,6 +100,7 @@ SWBOOL LoadScriptFile(const char *filename) ASSERT(readsize == size); + scriptbuffer[readsize] = '\0'; // Convert filebuffer to all upper case //Bstrupr(scriptbuffer); @@ -401,6 +405,7 @@ enum CM_MAXAMMO, CM_DAMAGEMIN, CM_DAMAGEMAX, + CM_THEME, CM_SECRET, CM_QUIT, }; @@ -421,6 +426,7 @@ static const struct _tokset { "inventory", CM_INVENTORY }, { "weapon", CM_WEAPON }, { "needkey", CM_NEEDKEY }, + { "theme", CM_THEME }, { "secret", CM_SECRET }, { "quit", CM_QUIT }, }, @@ -472,14 +478,20 @@ static const struct _tokset { "maxdamage", CM_DAMAGEMAX }, { "pickup", CM_AMOUNT }, { "weaponpickup",CM_WEAPON }, -} -; +}, +cm_theme_tokens[] = { + { "song", CM_SONG }, + { "music", CM_SONG }, + { "cdatrack", CM_CDATRACK }, + { "cdtrack", CM_CDATRACK }, +}; #define cm_numtokens (sizeof(cm_tokens)/sizeof(cm_tokens[0])) #define cm_map_numtokens (sizeof(cm_map_tokens)/sizeof(cm_map_tokens[0])) #define cm_episode_numtokens (sizeof(cm_episode_tokens)/sizeof(cm_episode_tokens[0])) #define cm_skill_numtokens (sizeof(cm_skill_tokens)/sizeof(cm_skill_tokens[0])) #define cm_inventory_numtokens (sizeof(cm_inventory_tokens)/sizeof(cm_inventory_tokens[0])) #define cm_weapons_numtokens (sizeof(cm_weapons_tokens)/sizeof(cm_weapons_tokens[0])) +#define cm_theme_numtokens (sizeof(cm_theme_tokens)/sizeof(cm_theme_tokens[0])) static int cm_transtok(const char *tok, const struct _tokset *set, const unsigned num) @@ -495,52 +507,6 @@ static int cm_transtok(const char *tok, const struct _tokset *set, const unsigne return -1; } -// level # { -// title "Map Name" -// filename "filename.map" -// song "filename.mid" -// cdatrack n -// besttime secs -// partime secs -// } -// -// episode # { -// title "Episode Name" -// subtitle "Caption text" -// } -// -// skill # { -// name "Tiny grasshopper" -// } -// -// fortune { -// "You never going to score." -// "26-31-43-82-16-29" -// "Sorry, you no win this time, try again." -// } -// gotkey { -// "Got the RED key!" -// "Got the BLUE key!" -// "Got the GREEN key!" -// ... -// } -// needkey { -// "You need a RED key for this door." -// "You need a BLUE key for this door." -// "You need a GREEN key for this door." -// ... -// } -// inventory # { name "Armour" amount 50 } -// weapon # { name "Uzi Submachine Gun" ammoname "Uzi Clip" maxammo 200 mindamage 5 maxdamage 7 pickup 50 } -// secret "You found a secret area!" -// quit "PRESS (Y) TO QUIT, (N) TO FIGHT ON." - -static LEVEL_INFO custommaps[MAX_LEVELS_REG]; -static char *customfortune[MAX_FORTUNES]; -static char *customkeymsg[MAX_KEYS]; -static char *customkeydoormsg[MAX_KEYS]; -static char *custominventoryname[InvDecl_TOTAL]; -static char *customweaponname[2][MAX_WEAPONS]; // weapon, ammo #define WM_DAMAGE 1 #define WM_WEAP 2 @@ -609,7 +575,7 @@ void LoadCustomInfoFromScript(const char *filename) mapnumptr = script->ltextptr; if (scriptfile_getbraces(script, &braceend)) break; - // first map file in LevelInfo[] is bogus, last map file is NULL + // first map entry may not be used, max. amount needs investigation if (curmap < 1 || curmap > MAX_LEVELS_REG) { initprintf("Error: map number %d not in range 1-%d on line %s:%d\n", @@ -630,9 +596,7 @@ void LoadCustomInfoFromScript(const char *filename) char *t; if (scriptfile_getstring(script, &t)) break; - //Bfree(custommaps[curmap].LevelName); - custommaps[curmap].LevelName = strdup(t); - LevelInfo[curmap].LevelName = custommaps[curmap].LevelName; + mapList[curmap].SetFileName(t); break; } case CM_SONG: @@ -640,9 +604,7 @@ void LoadCustomInfoFromScript(const char *filename) char *t; if (scriptfile_getstring(script, &t)) break; - //Bfree(custommaps[curmap].SongName); - custommaps[curmap].SongName = strdup(t); - LevelInfo[curmap].SongName = custommaps[curmap].SongName; + mapList[curmap].music = t; break; } case CM_TITLE: @@ -650,9 +612,7 @@ void LoadCustomInfoFromScript(const char *filename) char *t; if (scriptfile_getstring(script, &t)) break; - //Bfree(custommaps[curmap].Description); - custommaps[curmap].Description = strdup(t); - LevelInfo[curmap].Description = custommaps[curmap].Description; + mapList[curmap].SetName(t); break; } case CM_BESTTIME: @@ -661,10 +621,7 @@ void LoadCustomInfoFromScript(const char *filename) char s[10]; if (scriptfile_getnumber(script, &n)) break; - Bsnprintf(s, 10, "%d : %02d", n/60, n%60); - //Bfree(custommaps[curmap].BestTime); - custommaps[curmap].BestTime = strdup(s); - LevelInfo[curmap].BestTime = custommaps[curmap].BestTime; + mapList[curmap].designerTime = (int)strtoll(s, nullptr, 0); break; } case CM_PARTIME: @@ -673,10 +630,7 @@ void LoadCustomInfoFromScript(const char *filename) char s[10]; if (scriptfile_getnumber(script, &n)) break; - Bsnprintf(s, 10, "%d : %02d", n/60, n%60); - //Bfree(custommaps[curmap].ParTime); - custommaps[curmap].ParTime = strdup(s); - LevelInfo[curmap].ParTime = custommaps[curmap].ParTime; + mapList[curmap].parTime = (int)strtoll(s, nullptr, 0); break; } case CM_CDATRACK: @@ -702,7 +656,6 @@ void LoadCustomInfoFromScript(const char *filename) epnumptr = script->ltextptr; if (scriptfile_getbraces(script, &braceend)) break; - // first map file in LevelInfo[] is bogus, last map file is NULL if ((unsigned)--curmap >= 2u) { initprintf("Error: episode number %d not in range 1-2 on line %s:%d\n", @@ -722,18 +675,14 @@ void LoadCustomInfoFromScript(const char *filename) { char *t; if (scriptfile_getstring(script, &t)) break; - - strncpy(&EpisodeNames[curmap][1], t, MAX_EPISODE_NAME_LEN); - EpisodeNames[curmap][MAX_EPISODE_NAME_LEN+1] = 0; + gVolumeNames[curmap] = t; break; } case CM_SUBTITLE: { char *t; if (scriptfile_getstring(script, &t)) break; - - strncpy(EpisodeSubtitles[curmap], t, MAX_EPISODE_SUBTITLE_LEN); - EpisodeSubtitles[curmap][MAX_EPISODE_SUBTITLE_LEN] = 0; + gVolumeSubtitles[curmap] = t; break; } default: @@ -753,7 +702,6 @@ void LoadCustomInfoFromScript(const char *filename) epnumptr = script->ltextptr; if (scriptfile_getbraces(script, &braceend)) break; - // first map file in LevelInfo[] is bogus, last map file is NULL if ((unsigned)--curmap >= 4u) { initprintf("Error: skill number %d not in range 1-4 on line %s:%d\n", @@ -774,8 +722,7 @@ void LoadCustomInfoFromScript(const char *filename) char *t; if (scriptfile_getstring(script, &t)) break; - strncpy(&SkillNames[curmap][1], t, MAX_SKILL_NAME_LEN); - SkillNames[curmap][MAX_SKILL_NAME_LEN+1] = 0; + gSkillNames[curmap] = t; break; } default: @@ -801,8 +748,7 @@ void LoadCustomInfoFromScript(const char *filename) if (fc == MAX_FORTUNES) continue; - customfortune[fc] = strdup(t); - if (customfortune[fc]) ReadFortune[fc] = customfortune[fc]; + quoteMgr.InitializeQuote(QUOTE_COOKIE + fc, t); fc++; } break; @@ -820,8 +766,7 @@ void LoadCustomInfoFromScript(const char *filename) if (fc == MAX_KEYS) continue; - customkeymsg[fc] = strdup(t); - if (customkeymsg[fc]) KeyMsg[fc] = customkeymsg[fc]; + quoteMgr.InitializeQuote(QUOTE_KEYMSG + fc, t); fc++; } break; @@ -839,8 +784,7 @@ void LoadCustomInfoFromScript(const char *filename) if (fc == MAX_KEYS) continue; - customkeydoormsg[fc] = strdup(t); - if (customkeydoormsg[fc]) KeyDoorMessage[fc] = customkeydoormsg[fc]; + quoteMgr.InitializeQuote(QUOTE_DOORMSG + fc, t); fc++; } break; @@ -887,9 +831,7 @@ void LoadCustomInfoFromScript(const char *filename) if (name) { - Bfree(custominventoryname[in]); - custominventoryname[in] = strdup(name); - InventoryDecls[in].name = custominventoryname[in]; + quoteMgr.InitializeQuote(QUOTE_INVENTORY + in, name); } if (amt >= 0) { @@ -962,9 +904,7 @@ void LoadCustomInfoFromScript(const char *filename) if (maxammo >= 0) DamageData[id].max_ammo = maxammo; if (name) { - Bfree(customweaponname[0][id]); - customweaponname[0][id] = strdup(name); - DamageData[id].weapon_name = customweaponname[0][id]; + quoteMgr.InitializeQuote(QUOTE_WPNFIST + in, name); } if (wpickup >= 0) DamageData[id].weapon_pickup = wpickup; } @@ -972,14 +912,57 @@ void LoadCustomInfoFromScript(const char *filename) { if (ammo) { - Bfree(customweaponname[1][id]); - customweaponname[1][id] = strdup(ammo); - DamageData[id].ammo_name = customweaponname[1][id]; + quoteMgr.InitializeQuote(QUOTE_AMMOFIST + in, name); } if (pickup >= 0) DamageData[id].ammo_pickup = pickup; } break; } + case CM_THEME: + { + char *epnumptr; + char *name = NULL; + int trak = -1; + + if (scriptfile_getnumber(script, &curmap)) break; epnumptr = script->ltextptr; + if (scriptfile_getbraces(script, &braceend)) break; + if ((unsigned)--curmap >= 6u) + { + initprintf("Error: theme number %d not in range 1-6 on line %s:%d\n", + curmap, script->filename, + scriptfile_getlinum(script,epnumptr)); + script->textptr = braceend; + break; + } + while (script->textptr < braceend) + { + if (!(token = scriptfile_gettoken(script))) break; + if (token == braceend) break; + switch (cm_transtok(token, cm_theme_tokens, cm_theme_numtokens)) + { + case CM_SONG: + if (scriptfile_getstring(script, &name)) break; + break; + case CM_CDATRACK: + if (scriptfile_getnumber(script, &trak)) break; + break; + default: + initprintf("Error on line %s:%d\n", + script->filename, + scriptfile_getlinum(script,script->ltextptr)); + break; + } + } + if (name) + { + ThemeSongs[curmap] = name; + } + if (trak >= 2) + { + ThemeTrack[curmap] = trak; + } + break; + } case CM_SECRET: case CM_QUIT: default: diff --git a/source/sw/src/sector.cpp b/source/sw/src/sector.cpp index 93611bec3..e62347ed8 100644 --- a/source/sw/src/sector.cpp +++ b/source/sw/src/sector.cpp @@ -46,6 +46,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "common_game.h" #include "light.h" #include "text.h" +#include "gstrings.h" +#include "secrets.h" BEGIN_SW_NS @@ -486,7 +488,7 @@ SectorSetup(void) { SINE_WAVE_FLOOR *swf; short near_sect = i, base_sect = i; - short swf_ndx = 0; + uint16_t swf_ndx = 0; short cnt = 0, sector_cnt; int range; int range_diff = 0; @@ -2087,11 +2089,14 @@ int DoTrapMatch(short match) void OperateTripTrigger(PLAYERp pp) { - SECTORp sectp = §or[pp->cursectnum]; - if (Prediction) return; + if (pp->cursectnum < 0) + return; + + SECTORp sectp = §or[pp->cursectnum]; + #if 0 // new method if (TEST(sectp->extra, SECTFX_TRIGGER)) @@ -2138,7 +2143,9 @@ OperateTripTrigger(PLAYERp pp) PlayerSound(DIGI_ANCIENTSECRET, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler|v3df_follow,pp); - sprintf(ds,"You found a secret area!"); + sprintf(ds, GStrings("TXTS_SECRET")); + SECRET_Trigger(pp->cursectnum); + PutStringInfo(pp, ds); // always give to the first player Player->SecretsFound++; @@ -2249,6 +2256,9 @@ OperateContinuousTrigger(PLAYERp pp) if (Prediction) return; + if (pp->cursectnum < 0) + return; + switch (LOW_TAG(pp->cursectnum)) { case TAG_TRIGGER_MISSILE_TRAP: @@ -2589,8 +2599,6 @@ int DoPlayerGrabStar(PLAYERp pp) void PlayerOperateEnv(PLAYERp pp) { - SECT_USERp sectu = SectUser[pp->cursectnum]; - SECTORp sectp = §or[pp->cursectnum]; SWBOOL found; if (Prediction) @@ -2730,8 +2738,10 @@ PlayerOperateEnv(PLAYERp pp) // // //////////////////////////// - if (sectu && sectu->damage) + SECT_USERp sectu; + if (pp->cursectnum >= 0 && (sectu = SectUser[pp->cursectnum]) && sectu->damage) { + SECTORp sectp = §or[pp->cursectnum]; if (TEST(sectu->flags, SECTFU_DAMAGE_ABOVE_SECTOR)) { PlayerTakeSectorDamage(pp); @@ -2761,7 +2771,7 @@ PlayerOperateEnv(PLAYERp pp) { OperateTripTrigger(pp); - if (TEST(sector[pp->cursectnum].extra, SECTFX_WARP_SECTOR)) + if (pp->cursectnum >= 0 && TEST(sector[pp->cursectnum].extra, SECTFX_WARP_SECTOR)) { if (!TEST(pp->Flags2, PF2_TELEPORTED)) { @@ -3168,7 +3178,7 @@ void movelava(char *dapic) offs2 = (LAVASIZ + 2) + 1 + ((intptr_t) lavabakpic); for (x = 0; x < LAVASIZ; x++) { - copybuf(offs, offs2, LAVASIZ >> 2); + memcpy(offs, offs2, LAVASIZ); offs += LAVASIZ; offs2 += LAVASIZ + 2; } diff --git a/source/sw/src/serp.cpp b/source/sw/src/serp.cpp index 0e4debd0f..04d0649f8 100644 --- a/source/sw/src/serp.cpp +++ b/source/sw/src/serp.cpp @@ -35,10 +35,10 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "track.h" #include "sector.h" #include "gamecontrol.h" +#include "mapinfo.h" BEGIN_SW_NS -extern uint8_t RedBookSong[40]; extern short BossSpriteNum[3]; DECISION SerpBattle[] = @@ -815,14 +815,13 @@ int DoDeathSpecial(short SpriteNum) { SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; - static SWBOOL alreadydid = FALSE; DoMatchEverything(NULL, sp->lotag, ON); - if (!SW_SHAREWARE && MusicEnabled() && !alreadydid) + if (!SW_SHAREWARE) { - PlaySong(0, RedBookSong[Level], TRUE, TRUE); - alreadydid = TRUE; + // Resume the regular music - in a hack-free fashion. + PlaySong(currentLevel->labelName, currentLevel->music, currentLevel->cdSongId); } BossSpriteNum[0] = -2; diff --git a/source/sw/src/settings.h b/source/sw/src/settings.h index 4eda4a023..299eb55c8 100644 --- a/source/sw/src/settings.h +++ b/source/sw/src/settings.h @@ -44,10 +44,6 @@ typedef struct uint8_t NetTimeLimit; // Limit time of game uint8_t NetColor; // Chosen color for player SWBOOL NetNuke; - //SWBOOL PlayCD; // Not implemented and no idea how to support it without the music assets. - char WaveformTrackName[MAXWAVEFORMTRACKLENGTH]; - SWBOOL Darts; - SWBOOL WeaponAutoSwitch; } GAME_SET, *GAME_SETp; extern const GAME_SET gs_defaults; diff --git a/source/sw/src/slidor.cpp b/source/sw/src/slidor.cpp index 697513cab..a1161d6d7 100644 --- a/source/sw/src/slidor.cpp +++ b/source/sw/src/slidor.cpp @@ -36,6 +36,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "interp.h" #include "text.h" #include "sprite.h" +#include "quotemgr.h" BEGIN_SW_NS @@ -176,7 +177,7 @@ DoSlidorMatch(PLAYERp pp, short match, SWBOOL manual) // SWBOOL 8 must be set for message to display if (TEST_BOOL4(fsp) && (gNet.MultiGameType == MULTI_GAME_COMMBAT || gNet.MultiGameType == MULTI_GAME_AI_BOTS)) { - if (pp && TEST_BOOL11(fsp)) PutStringInfo(pp,"This only opens in single play."); + if (pp && TEST_BOOL11(fsp)) PutStringInfo(pp, GStrings("TXTS_SPONLY")); continue; } @@ -213,7 +214,7 @@ DoSlidorMatch(PLAYERp pp, short match, SWBOOL manual) else #endif { - PutStringInfo(pp, KeyDoorMessage[key_num - 1]); + PutStringInfo(pp, quoteMgr.GetExQuote(QUOTE_DOORMSG + key_num - 1)); return -1; } } diff --git a/source/sw/src/sounds.cpp b/source/sw/src/sounds.cpp index 1adb8b18c..95d534544 100644 --- a/source/sw/src/sounds.cpp +++ b/source/sw/src/sounds.cpp @@ -50,6 +50,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "rts.h" #include "menus.h" #include "config.h" +#include "menu/menu.h" +#include "z_music.h" #ifdef _WIN32 #include "sdlayer.h" @@ -70,24 +72,15 @@ int PLocked_Sounds[] = 558,557 }; -uint8_t RedBookSong[40] = -{ - 2,4,9,12,10, // Title and ShareWare levels - 5,6,8,11,12,5,10,4,6,9,7,10,8,7,9,10,11,5, // Registered levels - 11,8,7,13,5,6, // Deathmatch levels - 13 // Fight boss -}; // Global vars used by ambient sounds to set spritenum of ambient sounds for later lookups in // the sprite array so FAFcansee can know the sound sprite's current sector location SWBOOL Use_SoundSpriteNum = FALSE; int16_t SoundSpriteNum = -1; // Always set this back to -1 for proper validity checking! -SWBOOL MusicInitialized = FALSE; SWBOOL FxInitialized = FALSE; void SoundCallBack(unsigned int num); -SWBOOL LoadSong(const char *track); #define MUSIC_ID -65536 @@ -120,19 +113,6 @@ int voice; int loopflag; -typedef enum -{ - SongTypeNone, - SongTypeMIDI, - SongTypeWave, -} SongType_t; - -char *SongPtr = NULL; -int SongLength = 0; -char *SongName = NULL; -int SongTrack = 0; -SongType_t SongType = SongTypeNone; -int SongVoice = -1; extern SWBOOL DemoMode; // @@ -253,27 +233,6 @@ int PlayerYellVocs[] = DIGI_PLAYERYELL3 }; -#if 0 -// DEBUG -void CheckSndData(char *file, int line) -{ - short i; - - //return; - - for (i = 0; iname) - continue; -#endif - - if (!Bstrcasecmp(name, vp->name)) - { - // vp->priority = pri; - strcpy(vp->name, new_name); - vp->pitch_lo = pitch_lo; - vp->pitch_hi = pitch_hi; - } - } - } - - fclose(fin); -} - extern short Level; +CVAR(Bool, sw_nothememidi, false, CVAR_ARCHIVE) -SWBOOL -PlaySong(char *song_file_name, int cdaudio_track, SWBOOL loop, SWBOOL restart) +SWBOOL PlaySong(const char* mapname, const char* song_file_name, int cdaudio_track, bool isThemeTrack) //(nullptr, nullptr, -1, false) starts the normal level music. { - if (!MusicEnabled()) + if (mapname == nullptr && song_file_name == nullptr && cdaudio_track == -1) { - return FALSE; + // Get the music defined for the current level. + } - - if (DemoMode) - return FALSE; - - if (!restart) + // Play CD audio if enabled. + if (cdaudio_track >= 0 && mus_redbook) { - if (SongType == SongTypeWave) + FStringf trackname("track%02d.ogg", cdaudio_track); + if (!Mus_Play(nullptr, trackname, true)) { - if (SongTrack > 0 && SongTrack == cdaudio_track) - { - // ogg replacement for a CD track - return TRUE; - } - else if (SongName && song_file_name && !strcmp(SongName, song_file_name)) - { - return TRUE; - } - } - else if (SongType == SongTypeMIDI) - { - if (SongName && song_file_name && !strcmp(SongName, song_file_name)) - { - return TRUE; - } + buildprintf("Can't find CD track %i!\n", cdaudio_track); } } - - StopSong(); - - if (!SW_SHAREWARE) - { - if (cdaudio_track >= 0 && mus_redbook) - { - char waveformtrack[MAXWAVEFORMTRACKLENGTH]; - Bstrncpy(waveformtrack, gs.WaveformTrackName, MAXWAVEFORMTRACKLENGTH - 1); - - char *numPos = Bstrstr(waveformtrack, "??"); - - if (numPos && (numPos-waveformtrack) < MAXWAVEFORMTRACKLENGTH - 2) - { - static const char *tracktypes[] = { ".flac", ".ogg" }; - const size_t tracknamebaselen = Bstrlen(waveformtrack); - size_t i; - - numPos[0] = '0' + (cdaudio_track / 10) % 10; - numPos[1] = '0' + cdaudio_track % 10; - - for (i = 0; i < ARRAY_SIZE(tracktypes); ++i) - { - waveformtrack[tracknamebaselen] = '\0'; - Bstrncat(waveformtrack, tracktypes[i], MAXWAVEFORMTRACKLENGTH - 1); - - if (LoadSong(waveformtrack)) - { - SongVoice = FX_Play(SongPtr, SongLength, 0, 0, 0, - 255, 255, 255, FX_MUSIC_PRIORITY, 1.f, MUSIC_ID); - if (SongVoice > FX_Ok) - { - SongType = SongTypeWave; - SongTrack = cdaudio_track; - SongName = Bstrdup(waveformtrack); - return TRUE; - } - } - } - - buildprintf("Can't find CD track %i!\n", cdaudio_track); - } - else - { - buildprintf("Make sure to have \"??\" as a placeholder for the track number in your WaveformTrackName!\n"); - buildprintf(" e.g. WaveformTrackName = \"MUSIC/Track??\"\n"); - } - } - } - - if (!song_file_name || !LoadSong(song_file_name)) - { - return FALSE; - } - - if (!memcmp(SongPtr, "MThd", 4)) - { - MUSIC_PlaySong(SongPtr, SongLength, MUSIC_LoopSong); - SongType = SongTypeMIDI; - SongName = strdup(song_file_name); - return TRUE; - } - else - { - SongVoice = FX_Play(SongPtr, SongLength, 0, 0, 0, - 255, 255, 255, FX_MUSIC_PRIORITY, 1.f, MUSIC_ID); - if (SongVoice > FX_Ok) - { - SongType = SongTypeWave; - SongName = strdup(song_file_name); - return TRUE; - } - } - - return FALSE; + else if (isThemeTrack && sw_nothememidi) return false; // The original SW source only used CD Audio for theme tracks, so this is optional. + return Mus_Play(nullptr, song_file_name, true); } void @@ -521,61 +329,11 @@ StopFX(void) FX_StopAllSounds(); } -void -StopSong(void) -{ - if (DemoMode) - return; - - if (SongType == SongTypeWave && SongVoice > 0) - { - FX_StopSound(SongVoice); - SongVoice = 0; - } - else if (SongType == SongTypeMIDI) - { - MUSIC_StopSong(); - } - SongType = SongTypeNone; - - DO_FREE_AND_NULL(SongName); - SongTrack = 0; - - if (SongPtr) - { - FreeMem(SongPtr); - SongPtr = 0; - SongLength = 0; - } -} - -void -PauseSong(SWBOOL pauseon) -{ - if (!MusicEnabled()) return; - - if (SongType == SongTypeWave && SongVoice > 0) - { - FX_PauseVoice(SongVoice, pauseon); - } -} - -void -SetSongVolume(int volume) -{ -} - -SWBOOL -SongIsPlaying(void) -{ - return FALSE; -} - void StopSound(void) { StopFX(); - StopSong(); + Mus_Stop(); } // @@ -745,7 +503,7 @@ SWBOOL CacheSound(int num, int type) if (!OpenSound(vp, handle, &length)) { sprintf(ds,"Could not open sound %s, num %d, priority %d\n",vp->name,num,vp->priority); - CON_ConMessage("%s", ds); + OSD_Printf("%s", ds); return FALSE; } @@ -797,7 +555,7 @@ int PlaySound(int num, int *x, int *y, int *z, Voc3D_Flags flags) // Don't play game sounds when in menus - //if (UsingMenus && (*x!=0 || *y!=0 || *z!=0)) return(-1); + //if (M_Active() && (*x!=0 || *y!=0 || *z!=0)) return(-1); // Weed out parental lock sounds if PLock is active if (adult_lockout || Global_PLock) @@ -864,7 +622,7 @@ int PlaySound(int num, int *x, int *y, int *z, Voc3D_Flags flags) // Assign voc to voc pointer vp = &voc[num]; - if (UsingMenus && *x==0 && *y==0 && *z==0) // Menus sound outdo everything + if (M_Active() && *x==0 && *y==0 && *z==0) // Menus sound outdo everything priority = 100; else priority = vp->priority; @@ -1058,7 +816,7 @@ void PlaySoundRTS(int rts_num) SWBOOL OpenSound(VOC_INFOp vp, FileReader &handle, int *length) { - handle = kopenFileReader(vp->name, 0); + handle = fileSystem.OpenFileReader(vp->name, 0); if (!handle.isOpen()) { @@ -1085,34 +843,6 @@ ReadSound(FileReader &handle, VOC_INFOp vp, int length) return 0; } -SWBOOL -LoadSong(const char *filename) -{ - auto fr = kopenFileReader(filename, 0); - if (!fr.isOpen()) - { - return FALSE; - } - - auto size = fr.GetLength(); - - auto ptr = (char *) AllocMem(size); - if (ptr == NULL) - { - return FALSE; - } - - if (fr.Read(ptr, size) != size) - { - FreeMem(ptr); - return FALSE; - } - SongPtr = ptr; - SongLength = size; - - return TRUE; -} - void SoundStartup(void) { @@ -1162,74 +892,11 @@ SoundShutdown(void) } -/* -=================== -= -= MusicStartup -= -=================== -*/ - -void MusicStartup(void) -{ - // if they chose None lets return - - buildprintf("Initializing MIDI driver... "); - - int status; - if ((status = MUSIC_Init(MusicDevice)) == MUSIC_Ok) - { - if (MusicDevice == ASS_AutoDetect) - MusicDevice = MIDI_GetDevice(); - } - else if ((status = MUSIC_Init(ASS_AutoDetect)) == MUSIC_Ok) - { - MusicDevice = MIDI_GetDevice(); - } - else - { - buildprintf("Music error: %s\n", MUSIC_ErrorString(status)); - mus_enabled = FALSE; - return; - } - - MusicInitialized = TRUE; - MUSIC_SetVolume(mus_volume); - - auto fil = kopenFileReader("swtimbr.tmb", 0); - - if (fil.isOpen()) - { - auto tmb = fil.Read(); - if (tmb.Size()) - AL_RegisterTimbreBank(tmb.Data()); - } -} - void COVER_SetReverb(int amt) { FX_SetReverb(amt); } -/* -=================== -= -= MusicShutdown -= -=================== -*/ - -void MusicShutdown(void) -{ - StopSong(); - - int status = MUSIC_Shutdown(); - if (status != MUSIC_Ok) - { - buildprintf("Music error: %s\n", MUSIC_ErrorString(status)); - } -} - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// @@ -1638,7 +1305,7 @@ DoUpdateSounds3D(void) int i; static SWBOOL MoveSkip8 = 0; - if (UsingMenus) return; + if (M_Active()) return; // This function is already only call 10x per sec, this widdles it down even more! MoveSkip8 = (MoveSkip8 + 1) & 15; diff --git a/source/sw/src/sounds.h b/source/sw/src/sounds.h index 791de9117..e5b4af630 100644 --- a/source/sw/src/sounds.h +++ b/source/sw/src/sounds.h @@ -84,16 +84,11 @@ SWBOOL CacheSound(int num, int type); void COVER_SetReverb(int amt); void UnInitSound(void); void InitFX(void); -void InitMusic(void); void StopFX(void); -void StopSong(void); -void PauseSong(SWBOOL pauseon); void StopSound(void); void StartAmbientSound(void); void StopAmbientSound(void); -SWBOOL PlaySong(char *song_file_name, int cdaudio_track, SWBOOL loop, SWBOOL restart); -void SetSongVolume(int volume); -SWBOOL SongIsPlaying(void); +SWBOOL PlaySong(const char *mapname, const char *song_file_name, int cdaudio_track, bool isThemeTrack = false); //(nullptr, nullptr, -1, false) starts the normal level music. void PlaySoundRTS(int rts_num); // diff --git a/source/sw/src/sprite.cpp b/source/sw/src/sprite.cpp index ae1fda491..2264b0838 100644 --- a/source/sw/src/sprite.cpp +++ b/source/sw/src/sprite.cpp @@ -47,6 +47,9 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "text.h" #include "slidor.h" #include "player.h" +#include "swcvar.h" +#include "quotemgr.h" +#include "v_text.h" BEGIN_SW_NS @@ -962,7 +965,7 @@ SpawnSprite(short stat, short id, STATEp state, short sectnum, int x, int y, int ASSERT(!Prediction); - PRODUCTION_ASSERT(sectnum >= 0 && sectnum < MAXSECTORS); + // PRODUCTION_ASSERT(sectnum >= 0 && sectnum < MAXSECTORS); SpriteNum = COVERinsertsprite(sectnum, stat); @@ -5504,29 +5507,6 @@ void ChoosePlayerGetSound(PLAYERp pp) PlayerSound(PlayerGetItemVocs[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); } -//#define MAX_FORTUNES 16 -// With PLOCK on, max = 11 -const char *ReadFortune[MAX_FORTUNES] = -{ - "You never going to score.", - "26-31-43-82-16-29", - "Sorry, you no win this time, try again.", - "You try harder get along. Be a nice man.", - "No man is island, except Lo Wang.", - "There is much death in future.", - "You should kill all business associates.", - "(c)1997,3DRealms fortune cookie company.", - "Your chi attracts many chicks.", - "Don't you know you the scum of society!?", - "You should not scratch yourself there.", - "Man who stand on toilet, high on pot.", - "Man who fart in church sit in own pew.", - "Man trapped in pantry has ass in jam.", - "Baseball wrong. Man with 4 balls cannot walk.", - "Man who buy drowned cat pay for wet pussy.", -}; - - SWBOOL CanGetWeapon(PLAYERp pp, short SpriteNum, int WPN) { USERp u = User[SpriteNum], pu; @@ -5562,31 +5542,19 @@ SWBOOL CanGetWeapon(PLAYERp pp, short SpriteNum, int WPN) return TRUE; } -const char *KeyMsg[MAX_KEYS] = -{ - "Got the RED key!", - "Got the BLUE key!", - "Got the GREEN key!", - "Got the YELLOW key!", - "Got the GOLD master key!", - "Got the SILVER master key!", - "Got the BRONZE master key!", - "Got the RED master key!" -}; - struct InventoryDecl_t InventoryDecls[InvDecl_TOTAL] = { - { "Armor Vest +50", 50 }, - { "Kevlar Armor Vest +100", 100 }, - { "MedKit +20", 20 }, - { "Fortune Cookie +50 BOOST", 50 }, - { "Portable MedKit", 100 }, - { "Gas Bomb", 1 }, - { "Flash Bomb", 2 }, - { "Caltrops", 3 }, - { "Night Vision Goggles", 100 }, - { "Repair Kit", 100 }, - { "Smoke Bomb", 100 }, + {50 }, + {100 }, + {20 }, + {50 }, + {100 }, + {1 }, + {2 }, + {3 }, + {100 }, + {100 }, + {100 }, }; #define ITEMFLASHAMT -8 @@ -5701,7 +5669,7 @@ KeyMain: if (pp->HasKey[key_num]) break; - PutStringInfo(Player+pnum, KeyMsg[key_num]); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_KEYMSG + key_num)); pp->HasKey[key_num] = TRUE; SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup @@ -5722,14 +5690,14 @@ KeyMain: if (u->spal == PALETTE_PLAYER3) { PlayerUpdateArmor(pp, 1000+InventoryDecls[InvDecl_Kevlar].amount); - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_Kevlar].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_Kevlar)); } else { if (pp->Armor < InventoryDecls[InvDecl_Armor].amount) { PlayerUpdateArmor(pp, 1000+InventoryDecls[InvDecl_Armor].amount); - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_Armor].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_Armor)); } else break; @@ -5758,7 +5726,7 @@ KeyMain: { SWBOOL putbackmax=FALSE; - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_SmMedkit].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_SmMedkit)); if (pp->MaxHealth == 200) { @@ -5788,17 +5756,15 @@ KeyMain: pp->MaxHealth = 200; if (pu->Health < 200) { - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_Booster].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_Booster)); PlayerUpdateHealth(pp, InventoryDecls[InvDecl_Booster].amount); // This is for health // over 100% // Say something witty if (pp == Player+myconnectindex && hud_messages) { - if (adult_lockout || Global_PLock) - sprintf(ds,"Fortune Say: %s\n",ReadFortune[STD_RANDOM_RANGE(10)]); - else - sprintf(ds,"Fortune Say: %s\n",ReadFortune[STD_RANDOM_RANGE(MAX_FORTUNES)]); - CON_Message("%s", ds); + int cookie = (adult_lockout || Global_PLock)? STD_RANDOM_RANGE(10) : STD_RANDOM_RANGE(MAX_FORTUNES); + // print to the console, and if active to the generic notify display. + Printf(PRINT_NOTIFY, TEXTCOLOR_SAPPHIRE "%s: %s\n", GStrings("TXTS_FORTUNE"), quoteMgr.GetQuote(QUOTE_COOKIE + cookie)); } SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup @@ -5823,7 +5789,7 @@ KeyMain: if (!pp->InventoryAmount[INVENTORY_MEDKIT] || pp->InventoryPercent[INVENTORY_MEDKIT] < InventoryDecls[InvDecl_Medkit].amount) { - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_Medkit].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_Medkit)); pp->InventoryPercent[INVENTORY_MEDKIT] = InventoryDecls[InvDecl_Medkit].amount; pp->InventoryAmount[INVENTORY_MEDKIT] = 1; PlayerUpdateInventory(pp, INVENTORY_MEDKIT); @@ -5846,7 +5812,7 @@ KeyMain: if (pp->InventoryAmount[INVENTORY_CHEMBOMB] < InventoryDecls[InvDecl_ChemBomb].amount) { - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_ChemBomb].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_ChemBomb)); pp->InventoryPercent[INVENTORY_CHEMBOMB] = 0; pp->InventoryAmount[INVENTORY_CHEMBOMB]++; PlayerUpdateInventory(pp, INVENTORY_CHEMBOMB); @@ -5861,7 +5827,7 @@ KeyMain: if (pp->InventoryAmount[INVENTORY_FLASHBOMB] < InventoryDecls[InvDecl_FlashBomb].amount) { - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_FlashBomb].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_FlashBomb)); pp->InventoryPercent[INVENTORY_FLASHBOMB] = 0; pp->InventoryAmount[INVENTORY_FLASHBOMB]++; PlayerUpdateInventory(pp, INVENTORY_FLASHBOMB); @@ -5876,7 +5842,7 @@ KeyMain: if (pp->InventoryAmount[INVENTORY_CALTROPS] < InventoryDecls[InvDecl_Caltrops].amount) { - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_Caltrops].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_Caltrops)); pp->InventoryPercent[INVENTORY_CALTROPS] = 0; pp->InventoryAmount[INVENTORY_CALTROPS]+=3; if (pp->InventoryAmount[INVENTORY_CALTROPS] > InventoryDecls[InvDecl_Caltrops].amount) @@ -5892,7 +5858,7 @@ KeyMain: case ICON_NIGHT_VISION: if (!pp->InventoryAmount[INVENTORY_NIGHT_VISION] || pp->InventoryPercent[INVENTORY_NIGHT_VISION] < InventoryDecls[InvDecl_NightVision].amount) { - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_NightVision].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_NightVision)); pp->InventoryPercent[INVENTORY_NIGHT_VISION] = InventoryDecls[InvDecl_NightVision].amount; pp->InventoryAmount[INVENTORY_NIGHT_VISION] = 1; PlayerUpdateInventory(pp, INVENTORY_NIGHT_VISION); @@ -5905,7 +5871,7 @@ KeyMain: case ICON_REPAIR_KIT: if (!pp->InventoryAmount[INVENTORY_REPAIR_KIT] || pp->InventoryPercent[INVENTORY_REPAIR_KIT] < InventoryDecls[InvDecl_RepairKit].amount) { - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_RepairKit].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_RepairKit)); pp->InventoryPercent[INVENTORY_REPAIR_KIT] = InventoryDecls[InvDecl_RepairKit].amount; pp->InventoryAmount[INVENTORY_REPAIR_KIT] = 1; PlayerUpdateInventory(pp, INVENTORY_REPAIR_KIT); @@ -5936,7 +5902,7 @@ KeyMain: case ICON_CLOAK: if (!pp->InventoryAmount[INVENTORY_CLOAK] || pp->InventoryPercent[INVENTORY_CLOAK] < InventoryDecls[InvDecl_Cloak].amount) { - PutStringInfo(Player+pnum, InventoryDecls[InvDecl_Cloak].name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_INVENTORY + InvDecl_Cloak)); pp->InventoryPercent[INVENTORY_CLOAK] = InventoryDecls[InvDecl_Cloak].amount; pp->InventoryAmount[INVENTORY_CLOAK] = 1; PlayerUpdateInventory(pp, INVENTORY_CLOAK); @@ -5959,8 +5925,7 @@ KeyMain: if (pp->WpnAmmo[WPN_STAR] >= DamageData[WPN_STAR].max_ammo) break; - sprintf(ds, gs.Darts ? "Darts" : "Shurikens"); - PutStringInfo(Player+pnum, DamageData[WPN_STAR].weapon_name); + PutStringInfo(Player+pnum, sw_darts? GStrings("TXTS_DARTS") : quoteMgr.GetQuote(QUOTE_WPNSHURIKEN)); PlayerUpdateAmmo(pp, WPN_STAR, DamageData[WPN_STAR].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -5970,7 +5935,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_STAR)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum <= WPN_STAR && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) break; @@ -5987,7 +5952,7 @@ KeyMain: if (pp->WpnAmmo[WPN_MINE] >= DamageData[WPN_MINE].max_ammo) break; //sprintf(ds,"Sticky Bombs"); - PutStringInfo(Player+pnum, DamageData[WPN_MINE].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNSTICKY)); PlayerUpdateAmmo(pp, WPN_MINE, DamageData[WPN_MINE].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -5998,7 +5963,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_MINE)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum > WPN_MINE && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) break; @@ -6016,7 +5981,7 @@ KeyMain: if (TEST(pp->Flags, PF_TWO_UZI) && pp->WpnAmmo[WPN_UZI] >= DamageData[WPN_UZI].max_ammo) break; //sprintf(ds,"UZI Submachine Gun"); - PutStringInfo(Player+pnum, DamageData[WPN_UZI].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNUZI)); // pp->WpnAmmo[WPN_UZI] += 50; PlayerUpdateAmmo(pp, WPN_UZI, DamageData[WPN_UZI].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup @@ -6041,7 +6006,7 @@ KeyMain: ChoosePlayerGetSound(pp); } - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum > WPN_UZI && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) @@ -6054,7 +6019,7 @@ KeyMain: if (pp->WpnAmmo[WPN_UZI] >= DamageData[WPN_UZI].max_ammo) break; //sprintf(ds,"UZI Clip"); - PutStringInfo(Player+pnum, DamageData[WPN_UZI].ammo_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_AMMOUZI)); PlayerUpdateAmmo(pp, WPN_UZI, DamageData[WPN_UZI].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6072,7 +6037,7 @@ KeyMain: if (TEST(pp->WpnFlags, BIT(WPN_MICRO)) && pp->WpnAmmo[WPN_MICRO] >= DamageData[WPN_MICRO].max_ammo) break; //sprintf(ds,"Missile Launcher"); - PutStringInfo(Player+pnum, DamageData[WPN_MICRO].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNLAUNCH)); // pp->WpnAmmo[WPN_MICRO] += 5; PlayerUpdateAmmo(pp, WPN_MICRO, DamageData[WPN_MICRO].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup @@ -6084,7 +6049,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_MICRO)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum > WPN_MICRO && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) break; @@ -6095,7 +6060,7 @@ KeyMain: if (pp->WpnAmmo[WPN_MICRO] >= DamageData[WPN_MICRO].max_ammo) break; //sprintf(ds,"Missiles"); - PutStringInfo(Player+pnum, DamageData[WPN_MICRO].ammo_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_AMMOLAUNCH)); PlayerUpdateAmmo(pp, WPN_MICRO, DamageData[WPN_MICRO].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6107,7 +6072,7 @@ KeyMain: if (pp->WpnRocketNuke != 1) { //sprintf(ds,"Nuclear Warhead"); - PutStringInfo(Player+pnum, DamageData[DMG_NUCLEAR_EXP].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNNUKE)); pp->WpnRocketNuke = DamageData[DMG_NUCLEAR_EXP].weapon_pickup; SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6140,7 +6105,7 @@ KeyMain: if (TEST(pp->WpnFlags, BIT(WPN_GRENADE)) && pp->WpnAmmo[WPN_GRENADE] >= DamageData[WPN_GRENADE].max_ammo) break; //sprintf(ds,"Grenade Launcher"); - PutStringInfo(Player+pnum, DamageData[WPN_GRENADE].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNGRENADE)); // pp->WpnAmmo[WPN_GRENADE] += 6; PlayerUpdateAmmo(pp, WPN_GRENADE, DamageData[WPN_GRENADE].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup @@ -6155,7 +6120,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_GRENADE)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum > WPN_GRENADE && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) break; @@ -6166,7 +6131,7 @@ KeyMain: if (pp->WpnAmmo[WPN_GRENADE] >= DamageData[WPN_GRENADE].max_ammo) break; //sprintf(ds,"Grenade Shells"); - PutStringInfo(Player+pnum, DamageData[WPN_GRENADE].ammo_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_AMMOGRENADE)); PlayerUpdateAmmo(pp, WPN_GRENADE, DamageData[WPN_GRENADE].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6184,7 +6149,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_ROCKET)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; InitWeaponRocket(pp); break; @@ -6211,7 +6176,7 @@ KeyMain: if (TEST(pp->WpnFlags, BIT(WPN_RAIL)) && pp->WpnAmmo[WPN_RAIL] >= DamageData[WPN_RAIL].max_ammo) break; //sprintf(ds,"Rail Gun"); - PutStringInfo(Player+pnum, DamageData[WPN_RAIL].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNRAILGUN)); PlayerUpdateAmmo(pp, WPN_RAIL, DamageData[WPN_RAIL].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6231,7 +6196,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_RAIL)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum > WPN_RAIL && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) break; @@ -6244,7 +6209,7 @@ KeyMain: if (pp->WpnAmmo[WPN_RAIL] >= DamageData[WPN_RAIL].max_ammo) break; //sprintf(ds,"Rail Gun Rods"); - PutStringInfo(Player+pnum, DamageData[WPN_RAIL].ammo_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_AMMORAILGUN)); PlayerUpdateAmmo(pp, WPN_RAIL, DamageData[WPN_RAIL].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6261,7 +6226,7 @@ KeyMain: if (TEST(pp->WpnFlags, BIT(WPN_SHOTGUN)) && pp->WpnAmmo[WPN_SHOTGUN] >= DamageData[WPN_SHOTGUN].max_ammo) break; //sprintf(ds,"Riot Gun"); - PutStringInfo(Player+pnum, DamageData[WPN_SHOTGUN].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNRIOT)); // pp->WpnAmmo[WPN_SHOTGUN] += 10; PlayerUpdateAmmo(pp, WPN_SHOTGUN, DamageData[WPN_SHOTGUN].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup @@ -6273,7 +6238,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_SHOTGUN)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum > WPN_SHOTGUN && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) break; @@ -6284,7 +6249,7 @@ KeyMain: if (pp->WpnAmmo[WPN_SHOTGUN] >= DamageData[WPN_SHOTGUN].max_ammo) break; //sprintf(ds,"Shotshells"); - PutStringInfo(Player+pnum, DamageData[WPN_SHOTGUN].ammo_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_AMMORIOT)); PlayerUpdateAmmo(pp, WPN_SHOTGUN, DamageData[WPN_SHOTGUN].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash on item pickup if (pp == Player+myconnectindex) @@ -6328,7 +6293,7 @@ KeyMain: if (TEST(pp->WpnFlags, BIT(WPN_HOTHEAD)) && pp->WpnAmmo[WPN_HOTHEAD] >= DamageData[WPN_HOTHEAD].max_ammo) break; //sprintf(ds,"Guardian Head"); - PutStringInfo(Player+pnum, DamageData[WPN_HOTHEAD].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNHEAD)); PlayerUpdateAmmo(pp, WPN_HOTHEAD, DamageData[WPN_HOTHEAD].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6342,7 +6307,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_NAPALM) | BIT(WPN_RING) | BIT(WPN_HOTHEAD)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum > WPN_HOTHEAD && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) break; @@ -6355,7 +6320,7 @@ KeyMain: if (pp->WpnAmmo[WPN_HOTHEAD] >= DamageData[WPN_HOTHEAD].max_ammo) break; //sprintf(ds,"Firebursts"); - PutStringInfo(Player+pnum, DamageData[WPN_HOTHEAD].ammo_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_AMMOHEAD)); PlayerUpdateAmmo(pp, WPN_HOTHEAD, DamageData[WPN_HOTHEAD].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6374,7 +6339,7 @@ KeyMain: if (TEST(pp->WpnFlags, BIT(WPN_HEART)) && pp->WpnAmmo[WPN_HEART] >= DamageData[WPN_HEART].max_ammo) break; //sprintf(ds,"Ripper Heart"); - PutStringInfo(Player+pnum, DamageData[WPN_HEART].weapon_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_WPNRIPPER)); PlayerUpdateAmmo(pp, WPN_HEART, DamageData[WPN_HEART].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6388,7 +6353,7 @@ KeyMain: break; SET(pp->WpnFlags, BIT(WPN_HEART)); - if (!gs.WeaponAutoSwitch) + if (!cl_weaponswitch) break; if (User[pp->PlayerSprite]->WeaponNum > WPN_HEART && User[pp->PlayerSprite]->WeaponNum != WPN_SWORD) @@ -6403,7 +6368,7 @@ KeyMain: if (pp->WpnAmmo[WPN_HEART] >= DamageData[WPN_HEART].max_ammo) break; //sprintf(ds,"Deathcoils"); - PutStringInfo(Player+pnum, DamageData[WPN_HEART].ammo_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_AMMORIPPER)); PlayerUpdateAmmo(pp, WPN_HEART, DamageData[WPN_HEART].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6444,7 +6409,7 @@ KeyMain: if (pp->WpnRocketHeat != 5) { //sprintf(ds,"Heat Seeker Card"); - PutStringInfo(Player+pnum, DamageData[DMG_NUCLEAR_EXP].ammo_name); + PutStringInfo(Player+pnum, quoteMgr.GetQuote(QUOTE_AMMONUKE)); pp->WpnRocketHeat = DamageData[DMG_NUCLEAR_EXP].ammo_pickup; SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) @@ -6812,11 +6777,11 @@ SpriteControl(void) u = User[i]; sp = User[i]->SpriteP; STATE_CONTROL(i, sp, u, StateTics) - ASSERT(nexti >= 0 ? User[nexti] != NULL : TRUE); + // ASSERT(nexti >= 0 ? User[nexti] != NULL : TRUE); #else ASSERT(User[i]); StateControl(i); - ASSERT(nexti >= 0 ? User[nexti] != NULL : TRUE); + // ASSERT(nexti >= 0 ? User[nexti] != NULL : TRUE); #endif } diff --git a/source/sw/src/sprite.h b/source/sw/src/sprite.h index 95c8f60f1..4682a1226 100644 --- a/source/sw/src/sprite.h +++ b/source/sw/src/sprite.h @@ -77,7 +77,6 @@ enum struct InventoryDecl_t { - const char *name; int amount; }; extern struct InventoryDecl_t InventoryDecls[InvDecl_TOTAL]; diff --git a/source/sw/src/sumo.cpp b/source/sw/src/sumo.cpp index c5a547105..565c71312 100644 --- a/source/sw/src/sumo.cpp +++ b/source/sw/src/sumo.cpp @@ -38,10 +38,10 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "weapon.h" #include "sector.h" #include "gamecontrol.h" +#include "mapinfo.h" BEGIN_SW_NS -extern uint8_t RedBookSong[40]; extern uint8_t playTrack; SWBOOL serpwasseen = FALSE; SWBOOL sumowasseen = FALSE; @@ -794,7 +794,6 @@ int DoSumoDeathMelt(short SpriteNum) { SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; - static SWBOOL alreadydid = FALSE; PlaySound(DIGI_SUMOFART, &sp->x, &sp->y, &sp->z, v3df_follow); @@ -803,10 +802,10 @@ int DoSumoDeathMelt(short SpriteNum) u->ID = 0; DoMatchEverything(NULL, sp->lotag, ON); - if (!SW_SHAREWARE && MusicEnabled() && !alreadydid) + if (!SW_SHAREWARE) { - PlaySong(0, RedBookSong[Level], TRUE, TRUE); - alreadydid = TRUE; + // Resume the regular music - in a hack-free fashion. + PlaySong(currentLevel->labelName, currentLevel->music, currentLevel->cdSongId); } BossSpriteNum[1] = -2; // Sprite is gone, set it back to keep it valid! @@ -882,25 +881,25 @@ BossHealthMeter(void) if (i == 0 && !serpwasseen) { serpwasseen = TRUE; - if (!SW_SHAREWARE && MusicEnabled()) + if (!SW_SHAREWARE) { - PlaySong(0, ThemeTrack[2], TRUE, TRUE); + PlaySong(nullptr, ThemeSongs[2], ThemeTrack[2], true); } } else if (i == 1 && !sumowasseen) { sumowasseen = TRUE; - if (!SW_SHAREWARE && MusicEnabled()) + if (!SW_SHAREWARE) { - PlaySong(0, ThemeTrack[3], TRUE, TRUE); + PlaySong(nullptr, ThemeSongs[3], ThemeTrack[3], true); } } else if (i == 2 && !zillawasseen) { zillawasseen = TRUE; - if (!SW_SHAREWARE && MusicEnabled()) + if (!SW_SHAREWARE) { - PlaySong(0, ThemeTrack[4], TRUE, TRUE); + PlaySong(nullptr, ThemeSongs[4], ThemeTrack[4], true); } } } @@ -919,13 +918,6 @@ BossHealthMeter(void) if (i == 2 && (!zillawasseen || BossSpriteNum[2] < 0)) continue; - // This is needed because of possible saved game situation - if (!SW_SHAREWARE && !triedplay) - { - PlaySong(0, ThemeTrack[i+2], TRUE, FALSE); - triedplay = TRUE; // Only try once, then give up - } - sp = &sprite[BossSpriteNum[i]]; u = User[BossSpriteNum[i]]; diff --git a/source/sw/src/swcvar.cpp b/source/sw/src/swcvar.cpp index 61dd2961d..eca95381f 100644 --- a/source/sw/src/swcvar.cpp +++ b/source/sw/src/swcvar.cpp @@ -1,3 +1,4 @@ #include "swcvar.h" CVAR(Bool, sw_ninjahack, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); +CVAR(Bool, sw_darts, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); diff --git a/source/sw/src/swcvar.h b/source/sw/src/swcvar.h index 8302d574e..41502f714 100644 --- a/source/sw/src/swcvar.h +++ b/source/sw/src/swcvar.h @@ -2,3 +2,4 @@ EXTERN_CVAR(Bool, sw_ninjahack) +EXTERN_CVAR(Bool, sw_darts) diff --git a/source/sw/src/text.cpp b/source/sw/src/text.cpp index a63b97b58..090e79437 100644 --- a/source/sw/src/text.cpp +++ b/source/sw/src/text.cpp @@ -49,18 +49,6 @@ BEGIN_SW_NS #define PANEL_SM_FONT_Y 3613 #define PANEL_SM_FONT_R 3625 -const char *KeyDoorMessage[MAX_KEYS] = -{ - "You need a RED key for this door.", - "You need a BLUE key for this door.", - "You need a GREEN key for this door.", - "You need a YELLOW key for this door.", - "You need a GOLD key for this door.", - "You need a SILVER key for this door.", - "You need a BRONZE key for this door.", - "You need a RED key for this door." -}; - void DisplaySummaryString(PLAYERp pp, short xs, short ys, short color, short shade, const char *buffer) { short size,x; @@ -284,7 +272,8 @@ void DisplayMiniBarNumber(PLAYERp pp, short xs, short ys, int number) rotatesprite((long)x << 16, (long)ys << 16, (1 << 16), 0, pic, 0, 0, - ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER | RS_ALIGN_L, + 0, 0, xdim - 1, ydim - 1); size = tilesiz[PANEL_FONT_G + (*ptr - '0')].x + 1; } @@ -310,7 +299,8 @@ void DisplayMiniBarSmString(PLAYERp pp, short xs, short ys, short pal, const cha pic = FRAG_FIRST_TILE + (*ptr - FRAG_FIRST_ASCII); rotatesprite((int)x << 16, (int)ys << 16, (1 << 16), 0, pic, 0, pal, - ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1); + ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER | RS_ALIGN_L, + 0, 0, xdim - 1, ydim - 1); } } @@ -447,8 +437,17 @@ void PutStringInfo(PLAYERp pp, const char *string) if (!hud_messages) return; - CON_ConMessage("%s", string); // Put it in the console too - PutStringInfoLine(pp, string); + Printf(PRINT_MEDIUM|PRINT_NOTIFY, "%s", string); // Put it in the console too + if (hud_messages == 1) PutStringInfoLine(pp, string); +} + +void GameInterface::DoPrintMessage(int prio, const char* string) +{ + if (!hud_messages) + return; + + Printf(prio | PRINT_NOTIFY, "%s", string); // Put it in the console too + if (hud_messages == 1) PutStringInfoLine(&Player[myconnectindex], string); } void PutStringInfoLine(PLAYERp pp, const char *string) @@ -475,22 +474,6 @@ void PutStringInfoLine(PLAYERp pp, const char *string) //PutStringInfoLine2(pp, ""); } -void PutStringInfoLine2(PLAYERp pp, const char *string) -{ - short x,y; - short w,h; - - if (pp-Player != myconnectindex) - return; - - MNU_MeasureString(string, &w, &h); - - x = TEXT_XCENTER(w); - y = TEXT_INFO_LINE(1); - - PutStringTimer(pp, x, y, string, GlobInfoStringTime); -} - void pMenuClearTextLine(PLAYERp pp) { pMenuClearTextLineID(pp, ID_TEXT, TEXT_INFO_LINE(0), PRI_FRONT_MAX); @@ -500,22 +483,4 @@ void pMenuClearTextLine(PLAYERp pp) #define TEXT_PLAYER_INFO_TIME (3) #define TEXT_PLAYER_INFO_Y (200 - 40) -void PutStringPlayerInfo(PLAYERp pp, const char *string) -{ - short x,y; - short w,h; - - if (pp-Player != myconnectindex) - return; - - if (!hud_messages) - return; - - MNU_MeasureString(string, &w, &h); - - x = TEXT_XCENTER(w); - y = TEXT_PLAYER_INFO_Y; - - PutStringTimer(pp, x, y, string, GlobInfoStringTime); -} END_SW_NS diff --git a/source/sw/src/track.cpp b/source/sw/src/track.cpp index a3a147f32..68935f81c 100644 --- a/source/sw/src/track.cpp +++ b/source/sw/src/track.cpp @@ -726,7 +726,7 @@ void SectorObjectSetupBounds(SECTOR_OBJECTp sop) { int xlow, ylow, xhigh, yhigh; - short sp_num, next_sp_num, sn, startwall, endwall; + short sp_num, next_sp_num, startwall, endwall; int i, k, j; SPRITEp BoundSprite; SWBOOL FoundOutsideLoop = FALSE, FoundSector = FALSE; @@ -846,7 +846,7 @@ SectorObjectSetupBounds(SECTOR_OBJECTp sop) sop->num_sectors++; } - ASSERT(sop->num_sectors < SIZ(SectorObject[0].sector)); + ASSERT((uint16_t)sop->num_sectors < SIZ(SectorObject[0].sector)); } // @@ -967,6 +967,7 @@ SectorObjectSetupBounds(SECTOR_OBJECTp sop) // sector // place all sprites on list + uint16_t sn; for (sn = 0; sn < (int)SIZ(sop->sp_num); sn++) { if (sop->sp_num[sn] == -1) @@ -1498,7 +1499,7 @@ PlaceSectorObjectsOnTracks(void) } } - ASSERT(sop->num_walls < SIZ(sop->xorig)); + ASSERT((uint16_t)sop->num_walls < SIZ(sop->xorig)); if (sop->track <= -1) continue; diff --git a/source/sw/src/vator.cpp b/source/sw/src/vator.cpp index ecba7c777..3a580ab85 100644 --- a/source/sw/src/vator.cpp +++ b/source/sw/src/vator.cpp @@ -36,6 +36,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "text.h" #include "sprite.h" #include "weapon.h" +#include "quotemgr.h" BEGIN_SW_NS @@ -199,7 +200,7 @@ short DoVatorOperate(PLAYERp pp, short sectnum) else #endif { - PutStringInfo(pp, KeyDoorMessage[key_num - 1]); + PutStringInfo(pp, quoteMgr.GetExQuote(QUOTE_DOORMSG + key_num - 1)); return FALSE; } } @@ -241,7 +242,7 @@ DoVatorMatch(PLAYERp pp, short match) // SWBOOL 8 must be set for message to display if (TEST_BOOL4(fsp) && (gNet.MultiGameType == MULTI_GAME_COMMBAT || gNet.MultiGameType == MULTI_GAME_AI_BOTS)) { - if (pp && TEST_BOOL11(fsp)) PutStringInfo(pp,"This only opens in single play."); + if (pp && TEST_BOOL11(fsp)) PutStringInfo(pp, GStrings("TXTS_SPONLY")); continue; } @@ -267,7 +268,7 @@ DoVatorMatch(PLAYERp pp, short match) else #endif { - PutStringInfo(pp, KeyDoorMessage[key_num - 1]); + PutStringInfo(pp, quoteMgr.GetExQuote(QUOTE_DOORMSG + key_num - 1)); return -1; } } diff --git a/source/sw/src/warp.cpp b/source/sw/src/warp.cpp index 8410530ac..0a801baba 100644 --- a/source/sw/src/warp.cpp +++ b/source/sw/src/warp.cpp @@ -54,7 +54,7 @@ WarpPlaneSectorInfo(short sectnum, SPRITEp *sp_ceiling, SPRITEp *sp_floor) if (Prediction) return FALSE; - if (!TEST(sector[sectnum].extra, SECTFX_WARP_SECTOR)) + if (sectnum < 0 || !TEST(sector[sectnum].extra, SECTFX_WARP_SECTOR)) return FALSE; TRAVERSE_SPRITE_STAT(headspritestat[STAT_WARP], i, nexti) diff --git a/source/sw/src/weapon.cpp b/source/sw/src/weapon.cpp index fdfcd7b56..c5f255cf8 100644 --- a/source/sw/src/weapon.cpp +++ b/source/sw/src/weapon.cpp @@ -48,6 +48,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "actor.h" #include "track.h" #include "player.h" +#include "gstrings.h" BEGIN_SW_NS @@ -2653,12 +2654,12 @@ STATE s_PaperShrapC[] = SWBOOL MissileHitMatch(short Weapon, short WeaponNum, short hit_sprite) { SPRITEp hsp = &sprite[hit_sprite]; - SPRITEp wp = &sprite[Weapon]; - USERp wu = User[Weapon]; if (WeaponNum <= -1) { ASSERT(Weapon >= 0); + SPRITEp wp = &sprite[Weapon]; + USERp wu = User[Weapon]; WeaponNum = wu->WeaponNum; // can be hit by SO only @@ -2777,7 +2778,7 @@ int DoLavaErupt(short SpriteNum) TRAVERSE_CONNECT(pnum) { pp = Player + pnum; - if (TEST(sector[pp->cursectnum].extra, SECTFX_TRIGGER)) + if (pp->cursectnum >= 0 && TEST(sector[pp->cursectnum].extra, SECTFX_TRIGGER)) { TRAVERSE_SPRITE_SECT(headspritesect[pp->cursectnum],i,nexti) { @@ -5760,8 +5761,6 @@ PlayerCheckDeath(PLAYERp pp, short Weapon) { SPRITEp sp = pp->SpriteP; USERp u = User[pp->PlayerSprite]; - SPRITEp wp = &sprite[Weapon]; - USERp wu = User[Weapon]; int SpawnZombie(PLAYERp pp, short); @@ -5786,6 +5785,9 @@ PlayerCheckDeath(PLAYERp pp, short Weapon) return TRUE; } + SPRITEp wp = &sprite[Weapon]; + USERp wu = User[Weapon]; + if (Weapon > -1 && (wu->ID == RIPPER_RUN_R0 || wu->ID == RIPPER2_RUN_R0)) pp->DeathType = PLAYER_DEATH_RIPPER; @@ -5828,14 +5830,14 @@ PlayerCheckDeath(PLAYERp pp, short Weapon) SWBOOL PlayerTakeDamage(PLAYERp pp, short Weapon) { + if (Weapon < 0) + return TRUE; + SPRITEp sp = pp->SpriteP; USERp u = User[pp->PlayerSprite]; SPRITEp wp = &sprite[Weapon]; USERp wu = User[Weapon]; - if (Weapon < 0) - return TRUE; - if (gNet.MultiGameType == MULTI_GAME_NONE) { // ZOMBIE special case for single play @@ -7465,94 +7467,94 @@ const char *DeathString(short SpriteNum) case NINJA_RUN_R0: return " "; case ZOMBIE_RUN_R0: - return "Zombie"; + return GStrings("Zombie"); case BLOOD_WORM: - return "Blood Worm"; + return GStrings("Blood Worm"); case SKEL_RUN_R0: - return "Skeletor Priest"; + return GStrings("Skeletor Priest"); case COOLG_RUN_R0: - return "Coolie Ghost"; + return GStrings("Coolie Ghost"); case GORO_RUN_R0: - return "Guardian"; + return GStrings("Guardian"); case HORNET_RUN_R0: - return "Hornet"; + return GStrings("Hornet"); case RIPPER_RUN_R0: - return "Ripper Hatchling"; + return GStrings("Ripper Hatchling"); case RIPPER2_RUN_R0: - return "Ripper"; + return GStrings("Ripper"); case BUNNY_RUN_R0: - return "Killer Rabbit"; + return GStrings("Killer Rabbit"); case SERP_RUN_R0: - return "Serpent god"; + return GStrings("Serpent god"); case GIRLNINJA_RUN_R0: - return "Girl Ninja"; + return GStrings("Girl Ninja"); case BLADE1: case BLADE2: case BLADE3: case 5011: - return "blade"; + return GStrings("blade"); case STAR1: - if (gs.Darts) return "dart"; - else return "shuriken"; + if (sw_darts) return GStrings("dart"); + else return GStrings("shuriken"); case CROSSBOLT: - return "crossbow bolt"; + return GStrings("crossbow bolt"); case SPEAR_R0: - return "spear"; + return GStrings("spear"); case LAVA_BOULDER: case LAVA_SHARD: - return "lava boulder"; + return GStrings("lava boulder"); case UZI_SMOKE: - return "Uzi"; + return GStrings("Uzi"); case UZI_SMOKE+2: - return "Evil Ninja Uzi"; + return GStrings("Evil Ninja Uzi"); case SHOTGUN_SMOKE: - return "shotgun"; + return GStrings("shotgun"); case MIRV_METEOR: case SERP_METEOR: - return "meteor"; + return GStrings("meteor"); case BOLT_THINMAN_R0: - return "rocket"; + return GStrings("rocket"); case BOLT_THINMAN_R1: - return "rail gun"; + return GStrings("rail gun"); case BOLT_THINMAN_R2: - return "enemy rocket"; + return GStrings("enemy rocket"); case BOLT_THINMAN_R4: // BunnyRocket - return "bunny rocket"; + return GStrings("bunny rocket"); case BOLT_EXP: - return "explosion"; + return GStrings("explosion"); case TANK_SHELL_EXP: - return "tank shell"; + return GStrings("tank shell"); case MUSHROOM_CLOUD: - return "nuclear bomb"; + return GStrings("nuclear bomb"); case GRENADE_EXP: - return "40mm grenade"; + return GStrings("40mm grenade"); case MICRO_EXP: - return "micro missile"; + return GStrings("micro missile"); case MINE_EXP: //case MINE_SHRAP: - return "sticky bomb"; + return GStrings("sticky bomb"); case NAP_EXP: - return "napalm"; + return GStrings("napalm"); case Vomit1: case Vomit2: - return "vomit"; + return GStrings("vomit"); case COOLG_FIRE: - return "Coolie Ghost phlem"; + return GStrings("Coolie Ghost phlem"); case SKULL_R0: - return "Accursed Head"; + return GStrings("Accursed Head"); case BETTY_R0: - return "Bouncing Betty"; + return GStrings("Bouncing Betty"); case SKULL_SERP: - return "Serpent god Protector"; + return GStrings("Serpent god Protector"); case FIREBALL1: case FIREBALL: case GORO_FIREBALL: case FIREBALL_FLAMES: - return "flames"; + return GStrings("flames"); case RADIATION_CLOUD: - return "radiation"; + return GStrings("radiation"); case CALTROPS: - return "caltrops"; + return GStrings("caltrops"); } return ""; } @@ -7607,9 +7609,11 @@ DoDamageTest(short Weapon) return 0; } -int -DoHitscanDamage(short Weapon, short hit_sprite) +static int DoHitscanDamage(short Weapon, uint16_t hit_sprite) { + if (hit_sprite >= MAXSPRITES) + return 0; + SPRITEp wp = &sprite[Weapon]; USERp wu = User[Weapon]; unsigned stat; @@ -7745,7 +7749,7 @@ void TraverseBreakableWalls(short start_sect, int x, int y, int z, short ang, in { sect = sectlist[sectlistplc++]; - ASSERT(sectlistplc < SIZ(sectlist)); + ASSERT((uint16_t)sectlistplc < SIZ(sectlist)); startwall = sector[sect].wallptr; endwall = startwall + sector[sect].wallnum; @@ -7795,7 +7799,7 @@ void TraverseBreakableWalls(short start_sect, int x, int y, int z, short ang, in if (k < 0) { sectlist[sectlistend++] = nextsector; - ASSERT(sectlistend < SIZ(sectlist)); + ASSERT((uint16_t)sectlistend < SIZ(sectlist)); } } @@ -10832,8 +10836,8 @@ SpawnFireballFlames(int16_t SpriteNum, int16_t enemy) { SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; - SPRITEp ep = &sprite[enemy]; - USERp eu = User[enemy]; + SPRITEp ep; + USERp eu; SPRITEp np; USERp nu; short New; @@ -10843,6 +10847,9 @@ SpawnFireballFlames(int16_t SpriteNum, int16_t enemy) if (enemy >= 0) { + ep = &sprite[enemy]; + eu = User[enemy]; + // test for already burned if (TEST(ep->extra, SPRX_BURNABLE) && ep->shade > 40) return -1; @@ -13021,6 +13028,9 @@ InitSpellRing(PLAYERp pp) if (!SW_SHAREWARE) PlaySound(DIGI_RFWIZ, &pp->posx, &pp->posy, &pp->posz, v3df_none); + if (pp->cursectnum < 0) + return; + for (missiles = 0, ang = ang_start; missiles < max_missiles; ang += ang_diff, missiles++) { SpriteNum = SpawnSprite(STAT_MISSILE_SKIP4, FIREBALL1, s_Ring, pp->cursectnum, pp->posx, pp->posy, pp->posz, ang, 0); @@ -13569,6 +13579,9 @@ InitSpellNapalm(PLAYERp pp) PlaySound(DIGI_NAPFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_none); + if (pp->cursectnum < 0) + return; + for (i = 0; i < SIZ(mp); i++) { SpriteNum = SpawnSprite(STAT_MISSILE, FIREBALL1, s_Napalm, pp->cursectnum, @@ -13729,6 +13742,9 @@ InitSpellMirv(PLAYERp pp) PlaySound(DIGI_MIRVFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_none); + if (pp->cursectnum < 0) + return 0; + SpriteNum = SpawnSprite(STAT_MISSILE, FIREBALL1, s_Mirv, pp->cursectnum, pp->posx, pp->posy, pp->posz + Z(12), pp->pang, MIRV_VELOCITY); @@ -14740,13 +14756,16 @@ InitStar(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -3); + PlaySound(DIGI_STAR, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; nz = pp->posz + pp->bob_z + Z(8); - PlaySound(DIGI_STAR, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); - // Spawn a shot // Inserting and setting up variables @@ -14871,6 +14890,9 @@ InitHeartAttack(PLAYERp pp) PlayerUpdateAmmo(pp, WPN_HEART, -1); + if (pp->cursectnum < 0) + return; + SpriteNum = SpawnSprite(STAT_MISSILE_SKIP4, BLOOD_WORM, s_BloodWorm, pp->cursectnum, pp->posx, pp->posy, pp->posz + Z(12), pp->pang, BLOOD_WORM_VELOCITY*2); @@ -14944,6 +14966,9 @@ InitHeartAttack(PLAYERp pp) PlayerUpdateAmmo(pp, WPN_HEART, -1); + if (pp->cursectnum < 0) + return; + SpriteNum = SpawnSprite(STAT_MISSILE_SKIP4, BLOOD_WORM, s_BloodWorm, pp->cursectnum, pp->posx, pp->posy, pp->posz + Z(12), pp->pang, BLOOD_WORM_VELOCITY*2); @@ -15259,6 +15284,9 @@ InitLaser(PLAYERp pp) PlaySound(DIGI_RIOTFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; @@ -15368,6 +15396,9 @@ InitRail(PLAYERp pp) // Make sprite shade brighter u->Vis = 128; + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; @@ -15549,17 +15580,30 @@ InitRocket(PLAYERp pp) DoPlayerBeginRecoil(pp, ROCKET_RECOIL_AMT); PlayerUpdateAmmo(pp, u->WeaponNum, -1); + if (pp->WpnRocketHeat) + { + switch (pp->WpnRocketType) + { + case 1: + pp->WpnRocketHeat--; + break; + } + } PlaySound(DIGI_RIOTFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; // Spawn a shot // Inserting and setting up variables + //nz = pp->posz + pp->bob_z + Z(12); nz = pp->posz + pp->bob_z + Z(8); w = SpawnSprite(STAT_MISSILE, BOLT_THINMAN_R0, &s_Rocket[0][0], pp->cursectnum, @@ -15595,7 +15639,6 @@ InitRocket(PLAYERp pp) switch (pp->WpnRocketType) { case 1: - pp->WpnRocketHeat--; SET(wu->Flags, SPR_FIND_PLAYER); wp->pal = wu->spal = 20; // Yellow break; @@ -15673,11 +15716,15 @@ InitBunnyRocket(PLAYERp pp) PlaySound(DIGI_BUNNYATTACK, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; // Spawn a shot // Inserting and setting up variables + //nz = pp->posz + pp->bob_z + Z(12); nz = pp->posz + pp->bob_z + Z(8); w = SpawnSprite(STAT_MISSILE, BOLT_THINMAN_R4, &s_BunnyRocket[0][0], pp->cursectnum, @@ -15783,11 +15830,15 @@ InitNuke(PLAYERp pp) // Make sprite shade brighter u->Vis = 128; + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; // Spawn a shot // Inserting and setting up variables + //nz = pp->posz + pp->bob_z + Z(12); nz = pp->posz + pp->bob_z + Z(8); w = SpawnSprite(STAT_MISSILE, BOLT_THINMAN_R0, &s_Rocket[0][0], pp->cursectnum, @@ -15972,6 +16023,9 @@ InitMicro(PLAYERp pp) if (TargetSortCount > MAX_MICRO) TargetSortCount = MAX_MICRO; + if (pp->cursectnum < 0) + return 0; + for (i = 0; i < MAX_MICRO; i++) { if (ts < &TargetSort[TargetSortCount] && ts->sprite_num >= 0) @@ -17528,6 +17582,9 @@ DoDefaultStat(short SpriteNum) int InitTracerUzi(PLAYERp pp) { + if (pp->cursectnum < 0) + return 0; + USERp u = User[pp->PlayerSprite]; SPRITEp wp, hsp; USERp wu; @@ -17546,6 +17603,7 @@ InitTracerUzi(PLAYERp pp) // Spawn a shot // Inserting and setting up variables + w = SpawnSprite(STAT_MISSILE, 0, s_Tracer, pp->cursectnum, nx, ny, nz, pp->pang, TRACER_VELOCITY); @@ -17843,17 +17901,18 @@ SWBOOL HitscanSpriteAdjust(short SpriteNum, short hit_wall) { SPRITEp sp = &sprite[SpriteNum]; - short w, nw, ang = sp->ang, wall_ang; + int16_t ang; int xvect,yvect; short sectnum; #if 1 - w = hit_wall; - nw = wall[w].point2; - wall_ang = NORM_ANGLE(getangle(wall[nw].x - wall[w].x, wall[nw].y - wall[w].y)); - if (hit_wall >= 0) + { + uint16_t const w = hit_wall; + uint16_t const nw = wall[hit_wall].point2; + int16_t const wall_ang = NORM_ANGLE(getangle(wall[nw].x - wall[w].x, wall[nw].y - wall[w].y)); ang = sp->ang = NORM_ANGLE(wall_ang + 512); + } else ang = sp->ang; #endif @@ -18542,6 +18601,9 @@ InitTurretRail(short SpriteNum, PLAYERp pp) if (SW_SHAREWARE) return FALSE; // JBF: verify + if (pp->cursectnum < 0) + return 0; + nx = sp->x; ny = sp->y; nz = sp->z; @@ -18598,6 +18660,8 @@ InitTurretLaser(short SpriteNum, PLAYERp pp) if (SW_SHAREWARE) return FALSE; // JBF: verify + if (pp->cursectnum < 0) + return 0; nx = sp->x; ny = sp->y; @@ -19387,12 +19451,16 @@ InitGrenade(PLAYERp pp) // Make sprite shade brighter u->Vis = 128; + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; nz = pp->posz + pp->bob_z + Z(8); // Spawn a shot // Inserting and setting up variables + w = SpawnSprite(STAT_MISSILE, GRENADE, &s_Grenade[0][0], pp->cursectnum, nx, ny, nz, pp->pang, GRENADE_VELOCITY); @@ -19554,12 +19622,16 @@ InitMine(PLAYERp pp) PlaySound(DIGI_MINETHROW, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + if (pp->cursectnum < 0) + return 0; + nx = pp->posx; ny = pp->posy; nz = pp->posz + pp->bob_z + Z(8); // Spawn a shot // Inserting and setting up variables + w = SpawnSprite(STAT_MISSILE, MINE, s_Mine, pp->cursectnum, nx, ny, nz, pp->pang, MINE_VELOCITY); @@ -19733,6 +19805,9 @@ InitFireball(PLAYERp pp) // Make sprite shade brighter u->Vis = 128; + if (pp->cursectnum < 0) + return 0; + nx += pp->posx; ny += pp->posy; @@ -20638,13 +20713,13 @@ void QueueReset(void) SWBOOL TestDontStick(short SpriteNum, short hit_sect, short hit_wall, int hit_z) { - SPRITEp sp = &sprite[SpriteNum]; - USERp u = User[SpriteNum]; WALLp wp; if (hit_wall < 0) { ASSERT(SpriteNum>=0); + SPRITEp sp = &sprite[SpriteNum]; + USERp u = User[SpriteNum]; hit_wall = NORM_WALL(u->ret); } diff --git a/source/sw/src/zilla.cpp b/source/sw/src/zilla.cpp index 70a557c4b..6193c911b 100644 --- a/source/sw/src/zilla.cpp +++ b/source/sw/src/zilla.cpp @@ -37,10 +37,10 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "track.h" #include "fx_man.h" #include "gamecontrol.h" +#include "mapinfo.h" BEGIN_SW_NS -extern uint8_t RedBookSong[40]; extern short BossSpriteNum[3]; ANIMATOR InitZillaCharge; @@ -769,7 +769,6 @@ int DoZillaDeathMelt(short SpriteNum) { SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; - static SWBOOL alreadydid = FALSE; if (RANDOM_RANGE(1000) > 800) SpawnGrenadeExp(SpriteNum); @@ -778,10 +777,10 @@ int DoZillaDeathMelt(short SpriteNum) RESET(u->Flags, SPR_JUMPING|SPR_FALLING|SPR_MOVED); //DoMatchEverything(NULL, sp->lotag, ON); - if (!SW_SHAREWARE && MusicEnabled() && !alreadydid) + if (!SW_SHAREWARE) { - PlaySong(0, RedBookSong[Level], TRUE, TRUE); - alreadydid = TRUE; + // Resume the regular music - in a hack-free fashion. + PlaySong(currentLevel->labelName, currentLevel->music, currentLevel->cdSongId); } //KeepActorOnFloor(SpriteNum); diff --git a/source/zmusic/i_music.cpp b/source/zmusic/i_music.cpp deleted file mode 100644 index c6d9f749c..000000000 --- a/source/zmusic/i_music.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* -** i_music.cpp -** Plays music -** -**--------------------------------------------------------------------------- -** Copyright 1998-2010 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#ifndef _WIN32 -#include -#include -#endif - -#include - -#include "m_argv.h" -#include "w_wad.h" -#include "c_dispatch.h" -#include "templates.h" -#include "stats.h" -#include "c_cvars.h" -#include "c_console.h" -#include "vm.h" -#include "v_text.h" -#include "i_sound.h" -#include "i_soundfont.h" -#include "s_music.h" -#include "doomstat.h" -#include "zmusic/zmusic.h" -#include "zmusic/musinfo.h" -#include "streamsources/streamsource.h" -#include "filereadermusicinterface.h" -#include "../libraries/zmusic/midisources/midisource.h" - - - -void I_InitSoundFonts(); - -EXTERN_CVAR (Int, snd_samplerate) -EXTERN_CVAR (Int, snd_mididevice) - -static bool ungzip(uint8_t *data, int size, std::vector &newdata); - -int nomusic = 0; - -#ifdef _WIN32 - -void I_InitMusicWin32(); - -#include "musicformats/win32/i_cd.h" -//========================================================================== -// -// CVAR: cd_drive -// -// Which drive (letter) to use for CD audio. If not a valid drive letter, -// let the operating system decide for us. -// -//========================================================================== -EXTERN_CVAR(Bool, cd_enabled); - -CUSTOM_CVAR(String, cd_drive, "", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) -{ - if (cd_enabled && !Args->CheckParm("-nocdaudio")) CD_Enable(self); -} - -//========================================================================== -// -// CVAR: cd_enabled -// -// Use the CD device? Can be overridden with -nocdaudio on the command line -// -//========================================================================== - -CUSTOM_CVAR(Bool, cd_enabled, true, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) -{ - if (self && !Args->CheckParm("-nocdaudio")) - CD_Enable(cd_drive); - else - CD_Enable(nullptr); -} - - -#endif - -//========================================================================== -// -// CVAR snd_musicvolume -// -// Maximum volume of MOD/stream music. -//========================================================================== - -CUSTOM_CVAR (Float, snd_musicvolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - if (self < 0.f) - self = 0.f; - else if (self > 1.f) - self = 1.f; - else - { - // Set general music volume. - ChangeMusicSetting(ZMusic::snd_musicvolume, nullptr, self); - if (GSnd != nullptr) - { - GSnd->SetMusicVolume(clamp(self * relative_volume * snd_mastervolume, 0, 1)); - } - // For music not implemented through the digital sound system, - // let them know about the change. - if (mus_playing.handle != nullptr) - { - mus_playing.handle->MusicVolumeChanged(); - } - else - { // If the music was stopped because volume was 0, start it now. - S_RestartMusic(); - } - } -} - -//========================================================================== -// -// Callbacks for the music system. -// -//========================================================================== - -static void tim_printfunc(int type, int verbosity_level, const char* fmt, ...) -{ - if (verbosity_level >= 3/*Timidity::VERB_DEBUG*/) return; // Don't waste time on diagnostics. - - va_list args; - va_start(args, fmt); - FString msg; - msg.VFormat(fmt, args); - va_end(args); - - switch (type) - { - case 2:// Timidity::CMSG_ERROR: - Printf(TEXTCOLOR_RED "%s\n", msg.GetChars()); - break; - - case 1://Timidity::CMSG_WARNING: - Printf(TEXTCOLOR_YELLOW "%s\n", msg.GetChars()); - break; - - case 0://Timidity::CMSG_INFO: - DPrintf(DMSG_SPAMMY, "%s\n", msg.GetChars()); - break; - } -} - -static void wm_printfunc(const char* wmfmt, va_list args) -{ - Printf(TEXTCOLOR_RED); - VPrintf(PRINT_HIGH, wmfmt, args); -} - -//========================================================================== -// -// other callbacks -// -//========================================================================== - -static short* dumb_decode_vorbis_(int outlen, const void* oggstream, int sizebytes) -{ - return GSnd->DecodeSample(outlen, oggstream, sizebytes, CODEC_Vorbis); -} - -static std::string mus_NicePath(const char* str) -{ - FString strv = NicePath(str); - return strv.GetChars(); -} - -static const char* mus_pathToSoundFont(const char* sfname, int type) -{ - auto info = sfmanager.FindSoundFont(sfname, type); - return info ? info->mFilename.GetChars() : nullptr; -} - -static MusicIO::SoundFontReaderInterface* mus_openSoundFont(const char* sfname, int type) -{ - return sfmanager.OpenSoundFont(sfname, type); -} - - -//========================================================================== -// -// Pass some basic working data to the music backend -// We do this once at startup for everything available. -// -//========================================================================== - -static void SetupGenMidi() -{ - // The OPL renderer should not care about where this comes from. - // Note: No I_Error here - this needs to be consistent with the rest of the music code. - auto lump = Wads.CheckNumForName("GENMIDI", ns_global); - if (lump < 0) - { - Printf("No GENMIDI lump found. OPL playback not available."); - return; - } - auto data = Wads.OpenLumpReader(lump); - - auto genmidi = data.Read(); - if (genmidi.Size() < 8 + 175 * 36 || memcmp(genmidi.Data(), "#OPL_II#", 8)) return; - ZMusic_SetGenMidi(genmidi.Data()+8); -} - -static void SetupWgOpn() -{ - int lump = Wads.CheckNumForFullName("xg.wopn"); - if (lump < 0) - { - return; - } - FMemLump data = Wads.ReadLump(lump); - ZMusic_SetWgOpn(data.GetMem(), (uint32_t)data.GetSize()); -} - -static void SetupDMXGUS() -{ - int lump = Wads.CheckNumForFullName("DMXGUS"); - if (lump < 0) - { - return; - } - FMemLump data = Wads.ReadLump(lump); - ZMusic_SetDmxGus(data.GetMem(), (uint32_t)data.GetSize()); -} - - - -//========================================================================== -// -// -// -//========================================================================== - -void I_InitMusic (void) -{ - I_InitSoundFonts(); - - snd_musicvolume.Callback (); - - nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound"); - -#ifdef _WIN32 - I_InitMusicWin32 (); -#endif // _WIN32 - - Callbacks callbacks; - - callbacks.Fluid_MessageFunc = Printf; - callbacks.GUS_MessageFunc = callbacks.Timidity_Messagefunc = tim_printfunc; - callbacks.WildMidi_MessageFunc = wm_printfunc; - callbacks.NicePath = mus_NicePath; - callbacks.PathForSoundfont = mus_pathToSoundFont; - callbacks.OpenSoundFont = mus_openSoundFont; - callbacks.DumbVorbisDecode = dumb_decode_vorbis_; - - ZMusic_SetCallbacks(&callbacks); - SetupGenMidi(); - SetupDMXGUS(); - SetupWgOpn(); -} - - -//========================================================================== -// -// -// -//========================================================================== - -void I_SetRelativeVolume(float vol) -{ - relative_volume = (float)vol; - ChangeMusicSetting(ZMusic::relative_volume, nullptr, (float)vol); - snd_musicvolume.Callback(); -} -//========================================================================== -// -// Sets relative music volume. Takes $musicvolume in SNDINFO into consideration -// -//========================================================================== - -void I_SetMusicVolume (double factor) -{ - factor = clamp(factor, 0., 2.0); - I_SetRelativeVolume((float)factor); -} - -//========================================================================== -// -// test a relative music volume -// -//========================================================================== - -CCMD(testmusicvol) -{ - if (argv.argc() > 1) - { - I_SetRelativeVolume((float)strtod(argv[1], nullptr)); - } - else - Printf("Current relative volume is %1.2f\n", relative_volume); -} - -//========================================================================== -// -// STAT music -// -//========================================================================== - -ADD_STAT(music) -{ - if (mus_playing.handle != nullptr) - { - return FString(mus_playing.handle->GetStats().c_str()); - } - return "No song playing"; -} - -//========================================================================== -// -// Common loader for the dumpers. -// -//========================================================================== - -static MIDISource *GetMIDISource(const char *fn) -{ - FString src = fn; - if (src.Compare("*") == 0) src = mus_playing.name; - - auto lump = Wads.CheckNumForName(src, ns_music); - if (lump < 0) lump = Wads.CheckNumForFullName(src); - if (lump < 0) - { - Printf("Cannot find MIDI lump %s.\n", src.GetChars()); - return nullptr; - } - - auto wlump = Wads.OpenLumpReader(lump); - - uint32_t id[32 / 4]; - - if (wlump.Read(id, 32) != 32 || wlump.Seek(-32, FileReader::SeekCur) != 0) - { - Printf("Unable to read lump %s\n", src.GetChars()); - return nullptr; - } - auto type = IdentifyMIDIType(id, 32); - if (type == MIDI_NOTMIDI) - { - Printf("%s is not MIDI-based.\n", src.GetChars()); - return nullptr; - } - - auto data = wlump.Read(); - auto source = CreateMIDISource(data.Data(), data.Size(), type); - - if (source == nullptr) - { - Printf("%s is not MIDI-based.\n", src.GetChars()); - return nullptr; - } - return source; -} - -//========================================================================== -// -// CCMD writewave -// -// If the current song can be represented as a waveform, dump it to -// the specified file on disk. The sample rate parameter is merely a -// suggestion, and the dumper is free to ignore it. -// -//========================================================================== - -UNSAFE_CCMD (writewave) -{ - if (argv.argc() >= 3 && argv.argc() <= 7) - { - auto source = GetMIDISource(argv[1]); - if (source == nullptr) return; - - EMidiDevice dev = MDEV_DEFAULT; - - if (argv.argc() >= 6) - { - if (!stricmp(argv[5], "WildMidi")) dev = MDEV_WILDMIDI; - else if (!stricmp(argv[5], "GUS")) dev = MDEV_GUS; - else if (!stricmp(argv[5], "Timidity") || !stricmp(argv[5], "Timidity++")) dev = MDEV_TIMIDITY; - else if (!stricmp(argv[5], "FluidSynth")) dev = MDEV_FLUIDSYNTH; - else if (!stricmp(argv[5], "OPL")) dev = MDEV_OPL; - else if (!stricmp(argv[5], "OPN")) dev = MDEV_OPN; - else if (!stricmp(argv[5], "ADL")) dev = MDEV_ADL; - else - { - Printf("%s: Unknown MIDI device\n", argv[5]); - return; - } - } - // We must stop the currently playing music to avoid interference between two synths. - auto savedsong = mus_playing; - S_StopMusic(true); - if (dev == MDEV_DEFAULT && snd_mididevice >= 0) dev = MDEV_FLUIDSYNTH; // The Windows system synth cannot dump a wave. - try - { - MIDIDumpWave(source, dev, argv.argc() < 6 ? nullptr : argv[6], argv[2], argv.argc() < 4 ? 0 : (int)strtol(argv[3], nullptr, 10), argv.argc() < 5 ? 0 : (int)strtol(argv[4], nullptr, 10)); - } - catch (const std::runtime_error& err) - { - Printf("MIDI dump failed: %s\n", err.what()); - } - - S_ChangeMusic(savedsong.name, savedsong.baseorder, savedsong.loop, true); - } - else - { - Printf ("Usage: writewave [subsong] [sample rate] [synth] [soundfont]\n" - " - use '*' as song name to dump the currently playing song\n" - " - use 0 for subsong and sample rate to play the default\n"); - } -} - -//========================================================================== -// -// CCMD writemidi -// -// Writes a given MIDI song to disk. This does not affect playback anymore, -// like older versions did. -// -//========================================================================== - -UNSAFE_CCMD(writemidi) -{ - if (argv.argc() != 3) - { - Printf("Usage: writemidi - use '*' as song name to dump the currently playing song\n"); - return; - } - auto source = GetMIDISource(argv[1]); - if (source == nullptr) return; - - std::vector midi; - bool success; - - source->CreateSMF(midi, 1); - auto f = FileWriter::Open(argv[2]); - if (f == nullptr) - { - Printf("Could not open %s.\n", argv[2]); - return; - } - success = (f->Write(&midi[0], midi.size()) == midi.size()); - delete f; - - if (!success) - { - Printf("Could not write to music file %s.\n", argv[2]); - } -} diff --git a/source/zmusic/i_soundfont.cpp b/source/zmusic/i_soundfont.cpp deleted file mode 100644 index f14e53842..000000000 --- a/source/zmusic/i_soundfont.cpp +++ /dev/null @@ -1,546 +0,0 @@ -/* -** i_soundfont.cpp -** The sound font manager for the MIDI synths -** -**--------------------------------------------------------------------------- -** Copyright 2018 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include -#include "i_soundfont.h" -#include "i_soundinternal.h" -#include "cmdlib.h" -#include "i_system.h" -#include "gameconfigfile.h" -#include "filereadermusicinterface.h" -#include "zmusic/zmusic.h" -#include "resourcefiles/resourcefile.h" - -//========================================================================== -// -// -// -//========================================================================== - -FSoundFontManager sfmanager; - -//========================================================================== -// -// returns both a file reader and the full name of the looked up file -// -//========================================================================== - -std::pair FSoundFontReader::LookupFile(const char *name) -{ - if (!IsAbsPath(name)) - { - for(int i = mPaths.Size()-1; i>=0; i--) - { - FString fullname = mPaths[i] + name; - auto fr = OpenFile(fullname); - if (fr.isOpen()) return std::make_pair(std::move(fr), fullname); - } - } - auto fr = OpenFile(name); - if (!fr.isOpen()) name = ""; - return std::make_pair(std::move(fr), name); -} - -//========================================================================== -// -// This adds a directory to the path list -// -//========================================================================== - -void FSoundFontReader::AddPath(const char *strp) -{ - if (*strp == 0) return; - if (!mAllowAbsolutePaths && IsAbsPath(strp)) return; // of no use so we may just discard it right away - int i = 0; - FString str = strp; - FixPathSeperator(str); - if (str.Back() != '/') str += '/'; // always let it end with a slash. - for (auto &s : mPaths) - { - if (pathcmp(s.GetChars(), str) == 0) - { - // move string to the back. - mPaths.Delete(i); - mPaths.Push(str); - return; - } - i++; - } - mPaths.Push(str); -} - -int FSoundFontReader::pathcmp(const char *p1, const char *p2) -{ - return mCaseSensitivePaths? strcmp(p1, p2) : stricmp(p1, p2); -} - -//========================================================================== -// -// -// -//========================================================================== - -FileReader FSoundFontReader::Open(const char *name, std::string& filename) -{ - FileReader fr; - if (name == nullptr) - { - fr = OpenMainConfigFile(); - filename = MainConfigFileName(); - } - else - { - auto res = LookupFile(name); - fr = std::move(res.first); - filename = res.second; - } - return fr; -} - -//========================================================================== -// -// -// -//========================================================================== - -MusicIO::FileInterface* FSoundFontReader::open_interface(const char* name) -{ - std::string filename; - - FileReader fr = Open(name, filename); - if (!fr.isOpen()) return nullptr; - auto fri = new FileReaderMusicInterface(fr); - fri->filename = std::move(filename); - return fri; -} - - -//========================================================================== -// -// The file interface for the backend -// -//========================================================================== - -struct MusicIO::FileInterface* FSoundFontReader::open_file(const char* name) -{ - return open_interface(name); -} - - -//========================================================================== -// -// Note that the file type has already been checked -// -//========================================================================== - -FSF2Reader::FSF2Reader(const char *fn) -{ - mMainConfigForSF2.Format("soundfont \"%s\"\n", fn); - mFilename = fn; -} - -//========================================================================== -// -// -// -//========================================================================== - -FileReader FSF2Reader::OpenMainConfigFile() -{ - FileReader fr; - if (mMainConfigForSF2.IsNotEmpty()) - { - fr.OpenMemory(mMainConfigForSF2.GetChars(), mMainConfigForSF2.Len()); - } - return fr; -} - -FileReader FSF2Reader::OpenFile(const char *name) -{ - FileReader fr; - if (mFilename.CompareNoCase(name) == 0) - { - fr.OpenFile(name); - } - return fr; -} - -//========================================================================== -// -// -// -//========================================================================== - -FZipPatReader::FZipPatReader(const char *filename) -{ - resf = FResourceFile::OpenResourceFile(filename, true); -} - -FZipPatReader::~FZipPatReader() -{ - if (resf != nullptr) delete resf; -} - -FileReader FZipPatReader::OpenMainConfigFile() -{ - return OpenFile("timidity.cfg"); -} - -FileReader FZipPatReader::OpenFile(const char *name) -{ - FileReader fr; - if (resf != nullptr) - { - auto lump = resf->FindLump(name); - if (lump != nullptr) - { - return lump->NewReader(); - } - } - return fr; -} - -//========================================================================== -// -// -// -//========================================================================== - -FPatchSetReader::FPatchSetReader(const char *filename) -{ -#ifndef _WIN32 - mCaseSensitivePaths = true; - const char *paths[] = { - "/usr/local/lib/timidity", - "/etc/timidity", - "/etc" - }; -#else - const char *paths[] = { - "C:/TIMIDITY", - "/TIMIDITY", - progdir - }; -#endif - mAllowAbsolutePaths = true; - FileReader fr; - if (fr.OpenFile(filename)) - { - mFullPathToConfig = filename; - } - else if (!IsAbsPath(filename)) - { - for(auto c : paths) - { - FStringf fullname("%s/%s", c, filename); - if (fr.OpenFile(fullname)) - { - mFullPathToConfig = fullname; - } - } - } - if (mFullPathToConfig.Len() > 0) - { - FixPathSeperator(mFullPathToConfig); - mBasePath = ExtractFilePath(mFullPathToConfig); - if (mBasePath.Len() > 0 && mBasePath.Back() != '/') mBasePath += '/'; - } -} - - -FileReader FPatchSetReader::OpenMainConfigFile() -{ - FileReader fr; - fr.OpenFile(mFullPathToConfig); - return fr; -} - -FileReader FPatchSetReader::OpenFile(const char *name) -{ - FString path; - if (IsAbsPath(name)) path = name; - else path = mBasePath + name; - FileReader fr; - fr.OpenFile(path); - return fr; -} - -//========================================================================== -// -// -// -//========================================================================== - -FLumpPatchSetReader::FLumpPatchSetReader(const char *filename) -{ - mLumpIndex = Wads.CheckNumForFullName(filename); - - mBasePath = filename; - FixPathSeperator(mBasePath); - mBasePath = ExtractFilePath(mBasePath); - if (mBasePath.Len() > 0 && mBasePath.Back() != '/') mBasePath += '/'; -} - -FileReader FLumpPatchSetReader::OpenMainConfigFile() -{ - return Wads.ReopenLumpReader(mLumpIndex); -} - -FileReader FLumpPatchSetReader::OpenFile(const char *name) -{ - FString path; - if (IsAbsPath(name)) return FileReader(); // no absolute paths in the lump directory. - path = mBasePath + name; - auto index = Wads.CheckNumForFullName(path); - if (index < 0) return FileReader(); - return Wads.ReopenLumpReader(index); -} - -//========================================================================== -// -// collects everything out of the soundfonts directory. -// This may either be .sf2 files or zipped GUS patch sets with a -// 'timidity.cfg' in the root directory. -// Other compression types are not supported, in particular not 7z because -// due to the solid nature of its archives would be too slow. -// -//========================================================================== - -void FSoundFontManager::ProcessOneFile(const FString &fn) -{ - auto fb = ExtractFileBase(fn, false); - auto fbe = ExtractFileBase(fn, true); - for (auto &sfi : soundfonts) - { - // We already got a soundfont with this name. Do not add again. - if (!sfi.mName.CompareNoCase(fb)) return; - } - - FileReader fr; - if (fr.OpenFile(fn)) - { - // Try to identify. We only accept .sf2 and .zip by content. All other archives are intentionally ignored. - char head[16] = { 0}; - fr.Read(head, 16); - if (!memcmp(head, "RIFF", 4) && !memcmp(head+8, "sfbkLIST", 8)) - { - FSoundFontInfo sft = { fb, fbe, fn, SF_SF2 }; - soundfonts.Push(sft); - } - if (!memcmp(head, "WOPL3-BANK\0", 11)) - { - FSoundFontInfo sft = { fb, fbe, fn, SF_WOPL }; - soundfonts.Push(sft); - } - if (!memcmp(head, "WOPN2-BANK\0", 11) || !memcmp(head, "WOPN2-B2NK\0", 11)) - { - FSoundFontInfo sft = { fb, fbe, fn, SF_WOPN }; - soundfonts.Push(sft); - } - else if (!memcmp(head, "PK", 2)) - { - auto zip = FResourceFile::OpenResourceFile(fn, true); - if (zip != nullptr) - { - if (zip->LumpCount() > 1) // Anything with just one lump cannot possibly be a packed GUS patch set so skip it right away and simplify the lookup code - { - auto zipl = zip->FindLump("timidity.cfg"); - if (zipl != nullptr) - { - // It seems like this is what we are looking for - FSoundFontInfo sft = { fb, fbe, fn, SF_GUS }; - soundfonts.Push(sft); - } - } - delete zip; - } - } - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FSoundFontManager::CollectSoundfonts() -{ - findstate_t c_file; - void *file; - - if (GameConfig != NULL && GameConfig->SetSection ("SoundfontSearch.Directories")) - { - const char *key; - const char *value; - - while (GameConfig->NextInSection (key, value)) - { - if (stricmp (key, "Path") == 0) - { - FString dir; - - dir = NicePath(value); - FixPathSeperator(dir); - if (dir.IsNotEmpty()) - { - if (dir.Back() != '/') dir += '/'; - FString mask = dir + '*'; - if ((file = I_FindFirst(mask, &c_file)) != ((void *)(-1))) - { - do - { - if (!(I_FindAttr(&c_file) & FA_DIREC)) - { - FStringf name("%s%s", dir.GetChars(), I_FindName(&c_file)); - ProcessOneFile(name); - } - } while (I_FindNext(file, &c_file) == 0); - I_FindClose(file); - } - } - } - } - } - - if (soundfonts.Size() == 0) - { - ProcessOneFile(NicePath("$PROGDIR/soundfonts/gzdoom.sf2")); - } -} - -//========================================================================== -// -// -// -//========================================================================== - -const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int allowed) const -{ - for(auto &sfi : soundfonts) - { - // an empty name will pick the first one in a compatible format. - if (allowed & sfi.type && (name == nullptr || *name == 0 || !sfi.mName.CompareNoCase(name) || !sfi.mNameExt.CompareNoCase(name))) - { - return &sfi; - } - } - // We did not find what we were looking for. Let's just return the first valid item that works with the given device. - for (auto &sfi : soundfonts) - { - if (allowed & sfi.type) - { - return &sfi; - } - } - return nullptr; -} - -//========================================================================== -// -// -// -//========================================================================== - -FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed) -{ - - // First check if the given name is inside the loaded resources. - // To avoid clashes this will only be done if the name has the '.cfg' extension. - // Sound fonts cannot be loaded this way. - if (name != nullptr) - { - const char *p = name + strlen(name) - 4; - if (p > name && !stricmp(p, ".cfg") && Wads.CheckNumForFullName(name) >= 0) - { - return new FLumpPatchSetReader(name); - } - } - - auto sfi = FindSoundFont(name, allowed); - if (sfi != nullptr) - { - if (sfi->type == SF_SF2) return new FSF2Reader(sfi->mFilename); - else return new FZipPatReader(sfi->mFilename); - } - // The sound font collection did not yield any good results. - // Next check if the file is a .sf file - if (allowed & SF_SF2) - { - FileReader fr; - if (fr.OpenFile(name)) - { - char head[16] = { 0}; - fr.Read(head, 16); - fr.Close(); - if (!memcmp(head, "RIFF", 4) && !memcmp(head+8, "sfbkLIST", 8)) - { - return new FSF2Reader(name); - } - } - } - if (allowed & SF_GUS) - { - FileReader fr; - if (fr.OpenFile(name)) - { - char head[16] = { 0 }; - fr.Read(head, 2); - fr.Close(); - if (!memcmp(head, "PK", 2)) // The only reason for this check is to block non-Zips. The actual validation will be done by FZipFile. - { - auto r = new FZipPatReader(name); - if (r->isOk()) return r; - delete r; - } - } - - // Config files are only accepted if they are named '.cfg', because they are impossible to validate. - const char *p = name + strlen(name) - 4; - if (p > name && !stricmp(p, ".cfg") && FileExists(name)) - { - return new FPatchSetReader(name); - } - } - return nullptr; - -} - -void I_InitSoundFonts() -{ - sfmanager.CollectSoundfonts(); -} - - diff --git a/source/zmusic/i_soundfont.h b/source/zmusic/i_soundfont.h deleted file mode 100644 index 76e20d1b1..000000000 --- a/source/zmusic/i_soundfont.h +++ /dev/null @@ -1,165 +0,0 @@ -#pragma once - -#include "doomtype.h" -#include "w_wad.h" -#include "files.h" -#include "filereadermusicinterface.h" - -struct FSoundFontInfo -{ - FString mName; // This is what the sounfont is identified with. It's the extension-less base file name - FString mNameExt; // Same with extension. Used for comparing with input names so they can be done with or without extension. - FString mFilename; // Full path to the backing file - this is needed by FluidSynth to load the sound font. - int type; -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FSoundFontReader : public MusicIO::SoundFontReaderInterface -// Yes, it's 3 copies of essentially the same interface, but since we want to keep the 3 renderers as isolated modules we have to pull in their own implementations here. -{ -protected: - // This is only doable for loose config files that get set as sound fonts. All other cases read from a contained environment where this does not apply. - bool mAllowAbsolutePaths = false; - // This has only meaning if being run on a platform with a case sensitive file system and loose files. - // When reading from an archive it will always be case insensitive, just like the lump manager. - bool mCaseSensitivePaths = false; - TArray mPaths; - - - int pathcmp(const char *p1, const char *p2); - - -public: - - virtual ~FSoundFontReader() {} - virtual FileReader OpenMainConfigFile() = 0; // this is special because it needs to be synthesized for .sf files and set some restrictions for patch sets - virtual FString MainConfigFileName() - { - return basePath() + "timidity.cfg"; - } - - virtual FileReader OpenFile(const char *name) = 0; - std::pair LookupFile(const char *name); - void AddPath(const char *str); - virtual FString basePath() const - { - return ""; // archived patch sets do not use paths - } - - virtual FileReader Open(const char* name, std::string &filename); - - // Timidity++ interface - struct MusicIO::FileInterface* open_file(const char* name) override; - void add_search_path(const char* name) override - { - return AddPath(name); - } - - MusicIO::FileInterface* open_interface(const char* name); - -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FSF2Reader : public FSoundFontReader -{ - FString mMainConfigForSF2; - FString mFilename; -public: - FSF2Reader(const char *filename); - virtual FileReader OpenMainConfigFile() override; - virtual FileReader OpenFile(const char *name) override; -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FZipPatReader : public FSoundFontReader -{ - FResourceFile *resf; -public: - FZipPatReader(const char *filename); - ~FZipPatReader(); - virtual FileReader OpenMainConfigFile() override; - virtual FileReader OpenFile(const char *name) override; - bool isOk() { return resf != nullptr; } -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FLumpPatchSetReader : public FSoundFontReader -{ - int mLumpIndex;; - FString mBasePath; - -public: - FLumpPatchSetReader(const char *filename); - virtual FileReader OpenMainConfigFile() override; - virtual FileReader OpenFile(const char *name) override; - virtual FString basePath() const override - { - return mBasePath; - } - -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FPatchSetReader : public FSoundFontReader -{ - FString mBasePath; - FString mFullPathToConfig; - -public: - FPatchSetReader(FileReader &reader); - FPatchSetReader(const char *filename); - virtual FileReader OpenMainConfigFile() override; - virtual FileReader OpenFile(const char *name) override; - virtual FString basePath() const override - { - return mBasePath; - } -}; - -//========================================================================== -// -// -// -//========================================================================== - -class FSoundFontManager -{ - TArray soundfonts; - - void ProcessOneFile(const FString & fn); - -public: - void CollectSoundfonts(); - const FSoundFontInfo *FindSoundFont(const char *name, int allowedtypes) const; - FSoundFontReader *OpenSoundFont(const char *name, int allowedtypes); - const auto &GetList() const { return soundfonts; } // This is for the menu - -}; - - -extern FSoundFontManager sfmanager; diff --git a/source/zmusic/music_config.cpp b/source/zmusic/music_config.cpp deleted file mode 100644 index 47486e8a3..000000000 --- a/source/zmusic/music_config.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/* -** music_config.cpp -** This forwards all CVAR changes to the music system. -** -**--------------------------------------------------------------------------- -** Copyright 1999-2016 Randy Heit -** Copyright 2005-2019 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include -#include -#include "c_cvars.h" -#include "s_music.h" -#include "zmusic/zmusic.h" - -//========================================================================== -// -// ADL Midi device -// -//========================================================================== - -#define FORWARD_CVAR(key) \ - decltype(*self) newval; \ - auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle, *self, &newval); \ - self = (decltype(*self))newval; \ - if (ret) S_MIDIDeviceChanged(-1, true); - -#define FORWARD_BOOL_CVAR(key) \ - int newval; \ - auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self, &newval); \ - self = !!newval; \ - if (ret) S_MIDIDeviceChanged(-1, true); - -#define FORWARD_STRING_CVAR(key) \ - auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self); \ - if (ret) S_MIDIDeviceChanged(-1, true); - - -CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(adl_chips_count); -} - -CUSTOM_CVAR(Int, adl_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(adl_emulator_id); -} - -CUSTOM_CVAR(Bool, adl_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(adl_run_at_pcm_rate); -} - -CUSTOM_CVAR(Bool, adl_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(adl_fullpan); -} - -CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(adl_bank); -} - -CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(adl_use_custom_bank); -} - -CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_STRING_CVAR(adl_custom_bank); -} - -CUSTOM_CVAR(Int, adl_volume_model, 3/*ADLMIDI_VolumeModel_DMX*/, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(adl_bank); -} - -//========================================================================== -// -// Fluidsynth MIDI device -// -//========================================================================== - -CUSTOM_CVAR(String, fluid_lib, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_STRING_CVAR(fluid_lib); -} - -CUSTOM_CVAR(String, fluid_patchset, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_STRING_CVAR(fluid_patchset); -} - -CUSTOM_CVAR(Float, fluid_gain, 0.5, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_gain); -} - -CUSTOM_CVAR(Bool, fluid_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(fluid_reverb); -} - -CUSTOM_CVAR(Bool, fluid_chorus, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(fluid_chorus); -} - -CUSTOM_CVAR(Int, fluid_voices, 128, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_voices); -} - -CUSTOM_CVAR(Int, fluid_interp, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_interp); -} - -CUSTOM_CVAR(Int, fluid_samplerate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_samplerate); -} - -CUSTOM_CVAR(Int, fluid_threads, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_threads); -} - -CUSTOM_CVAR(Float, fluid_reverb_roomsize, 0.61f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_reverb_roomsize); -} - -CUSTOM_CVAR(Float, fluid_reverb_damping, 0.23f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_reverb_damping); -} - -CUSTOM_CVAR(Float, fluid_reverb_width, 0.76f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_reverb_width); -} - -CUSTOM_CVAR(Float, fluid_reverb_level, 0.57f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_reverb_level); -} - -CUSTOM_CVAR(Int, fluid_chorus_voices, 3, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_chorus_voices); -} - -CUSTOM_CVAR(Float, fluid_chorus_level, 1.2f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_chorus_level); -} - -CUSTOM_CVAR(Float, fluid_chorus_speed, 0.3f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_chorus_speed); -} - -// depth is in ms and actual maximum depends on the sample rate -CUSTOM_CVAR(Float, fluid_chorus_depth, 8, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_chorus_depth); -} - -CUSTOM_CVAR(Int, fluid_chorus_type, 0/*FLUID_CHORUS_DEFAULT_TYPE*/, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(fluid_chorus_type); -} - - -//========================================================================== -// -// OPL MIDI device -// -//========================================================================== - -CUSTOM_CVAR(Int, opl_numchips, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(opl_numchips); -} - -CUSTOM_CVAR(Int, opl_core, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(opl_core); -} - -CUSTOM_CVAR(Bool, opl_fullpan, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(opl_fullpan); -} - -//========================================================================== -// -// OPN MIDI device -// -//========================================================================== - - -CUSTOM_CVAR(Int, opn_chips_count, 8, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(opn_chips_count); -} - -CUSTOM_CVAR(Int, opn_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(opn_emulator_id); -} - -CUSTOM_CVAR(Bool, opn_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(opn_run_at_pcm_rate); -} - -CUSTOM_CVAR(Bool, opn_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(opn_fullpan); -} - -CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(opn_use_custom_bank); -} - -CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_STRING_CVAR(opn_custom_bank); -} - -//========================================================================== -// -// GUS MIDI device -// -//========================================================================== - - -CUSTOM_CVAR(String, midi_config, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_STRING_CVAR(gus_config); -} - -CUSTOM_CVAR(Bool, midi_dmxgus, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) // This was 'true' but since it requires special setup that's not such a good idea. -{ - FORWARD_BOOL_CVAR(gus_dmxgus); -} - -CUSTOM_CVAR(String, gus_patchdir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_STRING_CVAR(gus_patchdir); -} - -CUSTOM_CVAR(Int, midi_voices, 32, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(gus_midi_voices); -} - -CUSTOM_CVAR(Int, gus_memsize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(gus_memsize); -} - -//========================================================================== -// -// Timidity++ device -// -//========================================================================== - -CUSTOM_CVAR(Bool, timidity_modulation_wheel, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_modulation_wheel); -} - -CUSTOM_CVAR(Bool, timidity_portamento, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_portamento); -} - -CUSTOM_CVAR(Int, timidity_reverb, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(timidity_reverb); -} - -CUSTOM_CVAR(Int, timidity_reverb_level, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(timidity_reverb_level); -} - -CUSTOM_CVAR(Int, timidity_chorus, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(timidity_chorus); -} - -CUSTOM_CVAR(Bool, timidity_surround_chorus, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_surround_chorus); -} - -CUSTOM_CVAR(Bool, timidity_channel_pressure, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_channel_pressure); -} - -CUSTOM_CVAR(Int, timidity_lpf_def, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(timidity_lpf_def); -} - -CUSTOM_CVAR(Bool, timidity_temper_control, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_temper_control); -} - -CUSTOM_CVAR(Bool, timidity_modulation_envelope, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_modulation_envelope); -} - -CUSTOM_CVAR(Bool, timidity_overlap_voice_allow, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_overlap_voice_allow); -} - -CUSTOM_CVAR(Bool, timidity_drum_effect, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_drum_effect); -} - -CUSTOM_CVAR(Bool, timidity_pan_delay, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(timidity_pan_delay); -} - -CUSTOM_CVAR(Float, timidity_drum_power, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) /* coef. of drum amplitude */ -{ - FORWARD_CVAR(timidity_drum_power); -} - -CUSTOM_CVAR(Int, timidity_key_adjust, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(timidity_key_adjust); -} - -CUSTOM_CVAR(Float, timidity_tempo_adjust, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(timidity_tempo_adjust); -} - -CUSTOM_CVAR(Float, min_sustain_time, 5000, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(min_sustain_time); -} - -CUSTOM_CVAR(String, timidity_config, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_STRING_CVAR(timidity_config); -} - -//========================================================================== -// -// WildMidi -// -//========================================================================== - -CUSTOM_CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_STRING_CVAR(wildmidi_config); -} - -CUSTOM_CVAR(Bool, wildmidi_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(wildmidi_reverb); -} - -CUSTOM_CVAR(Bool, wildmidi_enhanced_resampling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(wildmidi_enhanced_resampling); -} - - -//========================================================================== -// -// This one is for Win32 MMAPI. -// -//========================================================================== - -CUSTOM_CVAR(Bool, snd_midiprecache, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(snd_midiprecache); -} - -//========================================================================== -// -// GME -// -//========================================================================== - -CUSTOM_CVAR(Float, gme_stereodepth, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(gme_stereodepth); -} - -//========================================================================== -// -// sndfile -// -//========================================================================== - -CUSTOM_CVAR(Int, snd_streambuffersize, 64, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(snd_streambuffersize); -} - -//========================================================================== -// -// Dumb -// -//========================================================================== - -CUSTOM_CVAR(Int, mod_samplerate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(mod_samplerate); -} - -CUSTOM_CVAR(Int, mod_volramp, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(mod_volramp); -} - -CUSTOM_CVAR(Int, mod_interp, 2/*DUMB_LQ_CUBIC*/, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(mod_interp); -} - -CUSTOM_CVAR(Bool, mod_autochip, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_BOOL_CVAR(mod_autochip); -} - -CUSTOM_CVAR(Int, mod_autochip_size_force, 100, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(mod_autochip_size_force); -} - -CUSTOM_CVAR(Int, mod_autochip_size_scan, 500, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(mod_autochip_size_scan); -} - -CUSTOM_CVAR(Int, mod_autochip_scan_threshold, 12, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(mod_autochip_scan_threshold); -} - -CUSTOM_CVAR(Float, mod_dumb_mastervolume, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) -{ - FORWARD_CVAR(mod_dumb_mastervolume); -} - diff --git a/source/zmusic/music_midi_base.cpp b/source/zmusic/music_midi_base.cpp deleted file mode 100644 index 6d08fe0e7..000000000 --- a/source/zmusic/music_midi_base.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* -** music_midi_base.cpp -** -**--------------------------------------------------------------------------- -** Copyright 1998-2010 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include -#include -#endif - -#include "c_dispatch.h" - -#include "v_text.h" -#include "menu/menu.h" -#include "zmusic/zmusic.h" -#include "s_music.h" - -static uint32_t nummididevices; -static bool nummididevicesset; - -#define NUM_DEF_DEVICES 7 - -static void AddDefaultMidiDevices(FOptionValues *opt) -{ - FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(NUM_DEF_DEVICES)]; - pair[0].Text = "FluidSynth"; - pair[0].Value = -5.0; - pair[1].Text = "TiMidity++"; - pair[1].Value = -2.0; - pair[2].Text = "WildMidi"; - pair[2].Value = -6.0; - pair[3].Text = "GUS"; - pair[3].Value = -4.0; - pair[4].Text = "OPL Synth Emulation"; - pair[4].Value = -3.0; - pair[5].Text = "libADL"; - pair[5].Value = -7.0; - pair[6].Text = "libOPN"; - pair[6].Value = -8.0; - -} - -#define DEF_MIDIDEV -5 - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include -#include - -CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - if (!nummididevicesset) - return; - - if ((self >= (signed)nummididevices) || (self < -8)) - { - // Don't do repeated message spam if there is no valid device. - if (self != 0) - { - Printf("ID out of range. Using default device.\n"); - self = DEF_MIDIDEV; - } - return; - } - else if (self == -1) self = DEF_MIDIDEV; - ChangeMusicSetting(ZMusic::snd_mididevice, nullptr, self); - S_MIDIDeviceChanged(self, false); -} - -void I_InitMusicWin32 () -{ - nummididevices = midiOutGetNumDevs (); - nummididevicesset = true; - snd_mididevice.Callback (); -} - -void I_BuildMIDIMenuList (FOptionValues *opt) -{ - AddDefaultMidiDevices(opt); - - for (uint32_t id = 0; id < nummididevices; ++id) - { - MIDIOUTCAPS caps; - MMRESULT res; - - res = midiOutGetDevCaps (id, &caps, sizeof(caps)); - assert(res == MMSYSERR_NOERROR); - if (res == MMSYSERR_NOERROR) - { - FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(1)]; - pair->Text = caps.szPname; - pair->Value = (float)id; - } - } -} - -static void PrintMidiDevice (int id, const char *name, uint16_t tech, uint32_t support) -{ - if (id == snd_mididevice) - { - Printf (TEXTCOLOR_BOLD); - } - Printf ("% 2d. %s : ", id, name); - switch (tech) - { - case MIDIDEV_MIDIPORT: Printf ("MIDIPORT"); break; - case MIDIDEV_SYNTH: Printf ("SYNTH"); break; - case MIDIDEV_SQSYNTH: Printf ("SQSYNTH"); break; - case MIDIDEV_FMSYNTH: Printf ("FMSYNTH"); break; - case MIDIDEV_MAPPER: Printf ("MAPPER"); break; - case MIDIDEV_WAVETABLE: Printf ("WAVETABLE"); break; - case MIDIDEV_SWSYNTH: Printf ("SWSYNTH"); break; - } - if (support & MIDICAPS_CACHE) - { - Printf (" CACHE"); - } - if (support & MIDICAPS_LRVOLUME) - { - Printf (" LRVOLUME"); - } - if (support & MIDICAPS_STREAM) - { - Printf (" STREAM"); - } - if (support & MIDICAPS_VOLUME) - { - Printf (" VOLUME"); - } - Printf (TEXTCOLOR_NORMAL "\n"); -} - -CCMD (snd_listmididevices) -{ - UINT id; - MIDIOUTCAPS caps; - MMRESULT res; - - PrintMidiDevice(-8, "libOPN", MIDIDEV_FMSYNTH, 0); - PrintMidiDevice(-7, "libADL", MIDIDEV_FMSYNTH, 0); - PrintMidiDevice (-6, "WildMidi", MIDIDEV_SWSYNTH, 0); - PrintMidiDevice (-5, "FluidSynth", MIDIDEV_SWSYNTH, 0); - PrintMidiDevice (-4, "Gravis Ultrasound Emulation", MIDIDEV_SWSYNTH, 0); - PrintMidiDevice (-3, "Emulated OPL FM Synth", MIDIDEV_FMSYNTH, 0); - PrintMidiDevice (-2, "TiMidity++", MIDIDEV_SWSYNTH, 0); - if (nummididevices != 0) - { - for (id = 0; id < nummididevices; ++id) - { - FString text; - res = midiOutGetDevCaps (id, &caps, sizeof(caps)); - if (res == MMSYSERR_NODRIVER) - text = ""; - else if (res == MMSYSERR_NOMEM) - text = ""; - else if (res == MMSYSERR_NOERROR) - text = caps.szPname; - else - continue; - - PrintMidiDevice (id, text, caps.wTechnology, caps.dwSupport); - } - } -} - -#else - -// Everything but Windows uses this code. - -CUSTOM_CVAR(Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ - if (self < -8) - self = -8; - else if (self > -2) - self = -2; - else - { - ChangeMusicSetting(ZMusic::snd_mididevice, nullptr, self); - S_MIDIDeviceChanged(self, false); - } -} - -void I_BuildMIDIMenuList (FOptionValues *opt) -{ - AddDefaultMidiDevices(opt); -} - -CCMD (snd_listmididevices) -{ - Printf("%s-8. libOPN\n", -8 == snd_mididevice ? TEXTCOLOR_BOLD : ""); - Printf("%s-7. libADL\n", -7 == snd_mididevice ? TEXTCOLOR_BOLD : ""); - Printf("%s-6. WildMidi\n", -6 == snd_mididevice ? TEXTCOLOR_BOLD : ""); - Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : ""); - Printf("%s-4. Gravis Ultrasound Emulation\n", -4 == snd_mididevice ? TEXTCOLOR_BOLD : ""); - Printf("%s-3. Emulated OPL FM Synth\n", -3 == snd_mididevice ? TEXTCOLOR_BOLD : ""); - Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : ""); -} -#endif diff --git a/source/zmusic/s_music.cpp b/source/zmusic/s_music.cpp deleted file mode 100644 index 3e8a536d6..000000000 --- a/source/zmusic/s_music.cpp +++ /dev/null @@ -1,633 +0,0 @@ -//----------------------------------------------------------------------------- -// -// Copyright 1993-1996 id Software -// Copyright 1999-2016 Randy Heit -// Copyright 2002-2016 Christoph Oelckers -// -// 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 -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//----------------------------------------------------------------------------- -// -// DESCRIPTION: none -// -//----------------------------------------------------------------------------- - -/* For code that originates from ZDoom the following applies: -** -**--------------------------------------------------------------------------- -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include -#ifdef _WIN32 -#include -#include "musicformats/win32/i_cd.h" -#endif - -#include "i_system.h" -#include "i_sound.h" -#include "i_music.h" - -#include "s_sound.h" -#include "s_sndseq.h" -#include "c_dispatch.h" -#include "m_random.h" -#include "w_wad.h" -#include "p_local.h" -#include "doomstat.h" -#include "cmdlib.h" -#include "v_video.h" -#include "v_text.h" -#include "a_sharedglobal.h" -#include "gstrings.h" -#include "gi.h" -#include "po_man.h" -#include "serializer.h" -#include "d_player.h" -#include "g_levellocals.h" -#include "vm.h" -#include "g_game.h" -#include "atterm.h" -#include "s_music.h" -#include "filereadermusicinterface.h" -#include "zmusic/musinfo.h" -#include "zmusic/zmusic.h" - -// MACROS ------------------------------------------------------------------ - - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -extern float S_GetMusicVolume (const char *music); - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static bool MusicPaused; // whether music is paused -MusPlayingInfo mus_playing; // music currently being played -float relative_volume = 1.f; -float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function - -DEFINE_GLOBAL_NAMED(mus_playing, musplaying); -DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, name); -DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, baseorder); -DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, loop); - -// PUBLIC DATA DEFINITIONS ------------------------------------------------- - -// CODE -------------------------------------------------------------------- - -//========================================================================== -// -// -// -// Create a sound system stream for the currently playing song -//========================================================================== - -static std::unique_ptr musicStream; - -static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) -{ - bool written = mus_playing.handle? mus_playing.handle->ServiceStream(buff, len) : 0; - if (!written) - { - memset((char*)buff, 0, len); - return false; - } - return true; -} - - -void S_CreateStream() -{ - if (!mus_playing.handle) return; - auto fmt = mus_playing.handle->GetStreamInfo(); - if (fmt.mBufferSize > 0) - { - int flags = fmt.mNumChannels < 0 ? 0 : SoundStream::Float; - if (abs(fmt.mNumChannels) < 2) flags |= SoundStream::Mono; - - musicStream.reset(GSnd->CreateStream(FillStream, fmt.mBufferSize, flags, fmt.mSampleRate, nullptr)); - if (musicStream) musicStream->Play(true, 1); - } -} - -void S_PauseStream(bool paused) -{ - if (musicStream) musicStream->SetPaused(paused); -} - -void S_StopStream() -{ - if (musicStream) - { - musicStream->Stop(); - musicStream.reset(); - } -} - - -//========================================================================== -// -// starts playing this song -// -//========================================================================== - -static void S_StartMusicPlaying(MusInfo* song, bool loop, float rel_vol, int subsong) -{ - if (rel_vol > 0.f) - { - float factor = relative_volume / saved_relative_volume; - saved_relative_volume = rel_vol; - I_SetRelativeVolume(saved_relative_volume * factor); - } - song->Stop(); - song->Play(loop, subsong); - song->m_NotStartedYet = false; - - // Notify the sound system of the changed relative volume - snd_musicvolume.Callback(); -} - - -//========================================================================== -// -// S_PauseSound -// -// Stop music and sound effects, during game PAUSE. -//========================================================================== - -void S_PauseMusic () -{ - if (mus_playing.handle && !MusicPaused) - { - mus_playing.handle->Pause(); - S_PauseStream(true); - MusicPaused = true; - } -} - -//========================================================================== -// -// S_ResumeSound -// -// Resume music and sound effects, after game PAUSE. -//========================================================================== - -void S_ResumeMusic () -{ - if (mus_playing.handle && MusicPaused) - { - mus_playing.handle->Resume(); - S_PauseStream(false); - MusicPaused = false; - } -} - -//========================================================================== -// -// S_UpdateSound -// -//========================================================================== - -void S_UpdateMusic () -{ - if (mus_playing.handle != nullptr) - { - mus_playing.handle->Update(); - - if (!mus_playing.handle->IsPlaying()) - { - S_StopMusic(true); - } - } -} - -//========================================================================== -// -// S_Start -// -// Per level startup code. Kills playing sounds at start of level -// and starts new music. -//========================================================================== - -void S_StartMusic () -{ - // stop the old music if it has been paused. - // This ensures that the new music is started from the beginning - // if it's the same as the last one and it has been paused. - if (MusicPaused) S_StopMusic(true); - - // start new music for the level - MusicPaused = false; - - // Don't start the music if loading a savegame, because the music is stored there. - // Don't start the music if revisiting a level in a hub for the same reason. - if (!primaryLevel->IsReentering()) - { - primaryLevel->SetMusic(); - } -} - -//========================================================================== -// -// S_StartMusic -// -// Starts some music with the given name. -//========================================================================== - -bool S_StartMusic (const char *m_id) -{ - return S_ChangeMusic (m_id, 0, false); -} - -//========================================================================== -// -// S_ChangeMusic -// -// Starts playing a music, possibly looping. -// -// [RH] If music is a MOD, starts it at position order. If name is of the -// format ",CD,,[cd id]" song is a CD track, and if [cd id] is -// specified, it will only be played if the specified CD is in a drive. -//========================================================================== - -bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) -{ - if (nomusic) return false; // skip the entire procedure if music is globally disabled. - - // allow specifying "*" as a placeholder to play the level's default music. - if (musicname != nullptr && !strcmp(musicname, "*")) - { - if (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL) - { - musicname = primaryLevel->Music; - order = primaryLevel->musicorder; - } - else - { - musicname = nullptr; - } - } - - if (musicname == nullptr || musicname[0] == 0) - { - // Don't choke if the map doesn't have a song attached - S_StopMusic (true); - mus_playing.name = ""; - mus_playing.LastSong = ""; - return true; - } - - FString DEH_Music; - if (musicname[0] == '$') - { - // handle dehacked replacement. - // Any music name defined this way needs to be prefixed with 'D_' because - // Doom.exe does not contain the prefix so these strings don't either. - const char * mus_string = GStrings[musicname+1]; - if (mus_string != nullptr) - { - DEH_Music << "D_" << mus_string; - musicname = DEH_Music; - } - } - - FName *aliasp = MusicAliases.CheckKey(musicname); - if (aliasp != nullptr) - { - if (*aliasp == NAME_None) - { - return true; // flagged to be ignored - } - musicname = aliasp->GetChars(); - } - - if (!mus_playing.name.IsEmpty() && - mus_playing.handle != nullptr && - stricmp (mus_playing.name, musicname) == 0 && - mus_playing.handle->m_Looping == looping) - { - if (order != mus_playing.baseorder) - { - if (mus_playing.handle->SetSubsong(order)) - { - mus_playing.baseorder = order; - } - } - else if (!mus_playing.handle->IsPlaying()) - { - try - { - mus_playing.handle->Play(looping, order); - S_CreateStream(); - } - catch (const std::runtime_error& err) - { - Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), err.what()); - } - - } - return true; - } - - { - int lumpnum = -1; - int length = 0; - MusInfo *handle = nullptr; - MidiDeviceSetting *devp = MidiDevices.CheckKey(musicname); - - // Strip off any leading file:// component. - if (strncmp(musicname, "file://", 7) == 0) - { - musicname += 7; - } - - FileReader reader; - if (!FileExists (musicname)) - { - if ((lumpnum = Wads.CheckNumForFullName (musicname, true, ns_music)) == -1) - { - Printf ("Music \"%s\" not found\n", musicname); - return false; - } - if (handle == nullptr) - { - if (Wads.LumpLength (lumpnum) == 0) - { - return false; - } - reader = Wads.ReopenLumpReader(lumpnum); - } - } - else - { - // Load an external file. - if (!reader.OpenFile(musicname)) - { - return false; - } - } - - // shutdown old music - S_StopMusic (true); - - // Just record it if volume is 0 - if (snd_musicvolume <= 0) - { - mus_playing.loop = looping; - mus_playing.name = musicname; - mus_playing.baseorder = order; - mus_playing.LastSong = musicname; - return true; - } - - // load & register it - if (handle != nullptr) - { - mus_playing.handle = handle; - } - else - { - try - { - auto mreader = new FileReaderMusicInterface(reader); - mus_playing.handle = ZMusic_OpenSong(mreader, devp? (EMidiDevice)devp->device : MDEV_DEFAULT, devp? devp->args.GetChars() : ""); - } - catch (const std::runtime_error& err) - { - Printf("Unable to load %s: %s\n", mus_playing.name.GetChars(), err.what()); - } - } - } - - mus_playing.loop = looping; - mus_playing.name = musicname; - mus_playing.baseorder = 0; - mus_playing.LastSong = ""; - - if (mus_playing.handle != 0) - { // play it - try - { - S_StartMusicPlaying(mus_playing.handle, looping, S_GetMusicVolume(musicname), order); - S_CreateStream(); - mus_playing.baseorder = order; - } - catch (const std::runtime_error& err) - { - Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), err.what()); - } - return true; - } - return false; -} - -//========================================================================== -// -// S_RestartMusic -// -// Must only be called from snd_reset in i_sound.cpp! -//========================================================================== - -void S_RestartMusic () -{ - if (!mus_playing.LastSong.IsEmpty()) - { - FString song = mus_playing.LastSong; - mus_playing.LastSong = ""; - S_ChangeMusic (song, mus_playing.baseorder, mus_playing.loop, true); - } -} - -//========================================================================== -// -// S_MIDIDeviceChanged -// -//========================================================================== - - -void S_MIDIDeviceChanged(int newdev, bool force) -{ - static int oldmididev = INT_MIN; - - // If a song is playing, move it to the new device. - if (oldmididev != newdev || force) - { - if (mus_playing.handle != nullptr && mus_playing.handle->IsMIDI()) - { - MusInfo* song = mus_playing.handle; - if (song->m_Status == MusInfo::STATE_Playing) - { - if (song->GetDeviceType() == MDEV_FLUIDSYNTH && force) - { - // FluidSynth must reload the song to change the patch set. - auto mi = mus_playing; - S_StopMusic(true); - S_ChangeMusic(mi.name, mi.baseorder, mi.loop); - } - else - { - song->Stop(); - S_StartMusicPlaying(song, song->m_Looping, -1, 0); - } - } - } - } - // 'force' - if (!force) oldmididev = newdev; -} - -//========================================================================== -// -// S_GetMusic -// -//========================================================================== - -int S_GetMusic (const char **name) -{ - int order; - - if (mus_playing.name.IsNotEmpty()) - { - *name = mus_playing.name; - order = mus_playing.baseorder; - } - else - { - *name = nullptr; - order = 0; - } - return order; -} - -//========================================================================== -// -// S_StopMusic -// -//========================================================================== - -void S_StopMusic (bool force) -{ - try - { - if (mus_playing.handle != nullptr) - { - S_ResumeMusic(); - S_StopStream(); - mus_playing.handle->Stop(); - delete mus_playing.handle; - mus_playing.handle = nullptr; - } - mus_playing.LastSong = std::move(mus_playing.name); - } - catch (const std::runtime_error& ) - { - //Printf("Unable to stop %s: %s\n", mus_playing.name.GetChars(), err.what()); - if (mus_playing.handle != nullptr) - { - delete mus_playing.handle; - mus_playing.handle = nullptr; - } - mus_playing.name = ""; - } -} - -//========================================================================== -// -// CCMD changemus -// -//========================================================================== - -CCMD (changemus) -{ - if (!nomusic) - { - if (argv.argc() > 1) - { - S_ChangeMusic (argv[1], argv.argc() > 2 ? atoi (argv[2]) : 0); - } - else - { - const char *currentmus = mus_playing.name.GetChars(); - if(currentmus != nullptr && *currentmus != 0) - { - Printf ("currently playing %s\n", currentmus); - } - else - { - Printf ("no music playing\n"); - } - } - } - else - { - Printf("Music is disabled\n"); - } -} - -//========================================================================== -// -// CCMD stopmus -// -//========================================================================== - -CCMD (stopmus) -{ - S_StopMusic (false); - mus_playing.LastSong = ""; // forget the last played song so that it won't get restarted if some volume changes occur -} - - -//========================================================================== -// -// -// -//========================================================================== - -CCMD(currentmusic) -{ - if (mus_playing.name.IsNotEmpty()) - { - Printf("Currently playing music '%s'\n", mus_playing.name.GetChars()); - } - else - { - Printf("Currently no music playing\n"); - } -} diff --git a/wadsrc/static/demolition/GENMIDI.op2 b/wadsrc/static/demolition/GENMIDI.op2 new file mode 100644 index 000000000..5c86b7787 Binary files /dev/null and b/wadsrc/static/demolition/GENMIDI.op2 differ diff --git a/wadsrc/static/demolition/commonbinds.txt b/wadsrc/static/demolition/commonbinds.txt new file mode 100644 index 000000000..9c45bf0a3 --- /dev/null +++ b/wadsrc/static/demolition/commonbinds.txt @@ -0,0 +1,65 @@ +// These bindings are valid for all configurationas + +F1 "openhelpmenu" +F2 "opensavemenu" +F3 "openloadmenu" +F4 "openmenu SoundOptions" +F5 "openmenu OptionMenu" //this key performs some fuckery with the music in Duke Nukem,so the default here is Blood's. +F6 "quicksave" +F7 "+Third_Person_View" +F8 "togglemessages" +F9 "quickload" +F10 "menu_endgame" +F11 "bumpgamma" +F12 "screenshot" +1 "+Weapon_1" +2 "+Weapon_2" +3 "+Weapon_3" +4 "+Weapon_4" +5 "+Weapon_5" +6 "+Weapon_6" +7 "+Weapon_7" +8 "+Weapon_8" +9 "+Weapon_9" +0 "+Weapon_10" +Ins "+Look_Left" +KP0 "+Look_Left" +Del "+Look_Right" +leftarrow "+Turn_Left" +rightarrow "+Turn_Right" +KP8 "+Move_Forward" +KP2 "+Move_Backward" +KP4 "+Turn_Left" +KP6 "+Turn_Right" +LAlt "+Strafe" +RAlt "+Strafe" +LShift "+Run" +RShift "+Run" +Capslock "toggle autorun 85" +PgUp "+Look_Up" +PgDn "+Look_Down" +Home "+Aim_Up" +End "+Aim_Down" +RCtrl "+Fire" +Scroll "+Holster_Weapon" + +Enter "+Inventory" +KP-Enter "+Inventory" +[ "+Inventory_Left" +] "+Inventory_Right" + +' "+Next_Weapon" +; "+Previous_Weapon" +` "toggleconsole" + +Backspace "+Turn_Around" +T "+Send_Message" +Tab "+Map" +F "+Map_Follow_Mode" +- "+Shrink_Screen" += "+Enlarge_Screen" +K "+See_Coop_View" + +Mouse1 "+Fire" +MWheelUp "+Previous_Weapon" +MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/demolition/confont.lmp b/wadsrc/static/demolition/confont.lmp new file mode 100644 index 000000000..3d46a3ca4 Binary files /dev/null and b/wadsrc/static/demolition/confont.lmp differ diff --git a/wadsrc/static/demolition/defbinds.txt b/wadsrc/static/demolition/defbinds.txt new file mode 100644 index 000000000..a5c467542 --- /dev/null +++ b/wadsrc/static/demolition/defbinds.txt @@ -0,0 +1,17 @@ +// Common bindings for all games (some may not be active everywhere, though) +W "+Move_Forward" +S "+Move_Backward" +E "+Open" +A "+Strafe_Left" +D "+Strafe_Right" +Space "+Jump" +/ "+Jump" +LCtrl "+Crouch" +KP7 "+Aim_Up" +KP1 "+Aim_Down" +KP5 "+Center_View" +KP9 "+Look_Up" +KP3 "+Look_Down" +KP- "+Shrink_Screen" +KP+ "+Enlarge_Screen" +Y "+Show_Opponents_Weapon" diff --git a/wadsrc/static/demolition/demolition.grpinfo b/wadsrc/static/demolition/demolition.grpinfo index 31e328efa..4e548e164 100644 --- a/wadsrc/static/demolition/demolition.grpinfo +++ b/wadsrc/static/demolition/demolition.grpinfo @@ -335,10 +335,10 @@ grpinfo grpinfo { - // This is for detecting zipped versions of the mod. The default configuration with all files dumped in the game filter requires starting the game with "-route66" + // This is for detecting zipped versions of the mod. name "Redneck Rampage: Suckin' Grits on Route 66" scriptname "GAME66.CON" - mustcontain "TILESA66.ART", "TILESB66.ART", "CARNIVAL.MAP", "TRUCKSTP.MAP", "GAME66.CON" + mustcontain "TILESA66.ART", "TILESB66.ART", "ROUTE66/CARNIVAL.MAP", "ROUTE66/TRUCKSTP.MAP", "GAME66.CON" flags GAMEFLAG_RR|GAMEFLAG_ADDON dependency RR_CRC loadart "TILESA66.ART", "TILESB66.ART" // replaces TILES009 and TILES023. @@ -358,6 +358,7 @@ grpinfo gamefilter "Blood.Blood" } +/* this doesn't work with the current setup. grpinfo { // This is for identifying older Blood versions. Since I have no information, all I can do is testing for a few known files. @@ -370,10 +371,11 @@ grpinfo loadgrp "SOUNDS.RFF", "GUI.RFF" gamefilter "Blood.Blood" } +*/ grpinfo { - // This is for detecting zipped versions of the mod. The default configuration with all files dumped in the game filter requires starting the game with "-cryptic" + // This is for detecting zipped versions of the mod. name "BLOOD: Cryptic Passage" scriptname "CRYPTIC.INI" mustcontain "CRYPTIC.INI", "CP01.MAP", "CP02.MAP" diff --git a/wadsrc/static/demolition/graphics/M_BACK.png b/wadsrc/static/demolition/graphics/M_BACK.png new file mode 100644 index 000000000..9d562600d Binary files /dev/null and b/wadsrc/static/demolition/graphics/M_BACK.png differ diff --git a/wadsrc/static/demolition/language.csv b/wadsrc/static/demolition/language.csv new file mode 100644 index 000000000..fb7fcba3e --- /dev/null +++ b/wadsrc/static/demolition/language.csv @@ -0,0 +1,2112 @@ +default,Identifier,Remarks,Filter,eng enc ena enz eni ens enj enb enl ent enw,cs,de,el,eo,es,esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu,fi,fr,hu,it,jp,ko,nl,pl,pt,ptg,ro,ru,sr +,,,,,,,,,,,,,,,,,,,,,,, +New Game,MNU_NEWGAME,,,,Nová hra,Neues Spiel,,Nova Ludo,Nueva Partida,,Uusi peli,Nouvelle Partie,,Nuovo gioco,æ–°è¦ã‚²ãƒ¼ãƒ ,새로운 게임,Nieuw spel,Nowa Gra,Novo Jogo,,,ÐÐ¾Ð²Ð°Ñ Ð¸Ð³Ñ€Ð°,Ðова игра +Options,MNU_OPTIONS,,,,Možnosti,Optionen,,Agordoj,Opciones,,Asetukset,Options,,Opzioni,オプション,설정,Opties,Opcje,Opções,,,ÐаÑтройки,Подешавања +Quit,MNU_QUITGAME,,,,UkonÄit hru,Spiel verlassen,,Ĉesigi Ludon,Salir del juego,,Lopeta peli,Quitter le jeu,,Esci dal gioco,終了,게임 종료,Verlaat spel,Wyjdź z Gry,Sair,,,Выход,Заврши игру +Load Game,MNU_LOADGAME,,,,NaÄíst hru,Spiel laden,,ÅœarÄi Ludon,Cargar Partida,,Lataa peli,Chargement,,Carica gioco,ロード,게임 불러오기,Laden spel,Wczytaj GrÄ™,Carregar,,,Загрузка,Учитај игру +Save Game,MNU_SAVEGAME,,,,Uložit hru,Spiel sichern,,Konservi Ludon,Guardar Partida,,Tallenna peli,Sauvegarde,,Salva gioco,セーブ,게임 저장하기,Opslaan spel,Zapisz GrÄ™,Salvar,Gravar,,Сохранение,Сачувај игру +Help,MNU_HELP,,,,,Hilfe,,,,,,Aide,,,,,,,,,,, +Continue,MNU_CONTINUE,,,,,Fortfahren,,,,,,,,,,,,,,,,, +Credits,MNU_CREDITS,,,,,,,,,,,,,,,,,,,,,, +How to Order,MNU_HOWTOORDER,,,,,Bestellen,,,,,,,,,,,,,,,,, +Cool Stuff,MNU_COOLSTUFF,Was removed,,,,Cooles Zeug,,,,,,,,,,,,,,,,, +Multiplayer,MNU_MULTIPLAYER,,,,,Mehrspieler,,,,,,,,,,,,,,,,, +End Game,MNU_ENDGAME,,,,,Spiel beenden,,,,,,,,,,,,,,,,, +User Map,MNU_USERMAP,,,,,Benutzerlevel,,,,,,,,,,,,,,,,, +Select a user map to play,MNU_SELECTUSERMAP,,,,,"Wähle ein Level zum Spielen +",,,,,,,,,,,,,,,,, +Select an Episode,MNU_SELECTEPISODE,DN3D et.al.,,,,"Welche Episode? +",,,,,,,,,,,,,,,,, +Episodes,MNU_EPISODES,Blood,,,,Episoden,,,,,,,,,,,,,,,,, +Select Skill,MNU_SELECTSKILL,DN3D et.al.,,,,Schwierigkeitsgrad,,,,,,,,,,,,,,,,, +Difficulty,MNU_DIFFICULTY,Blood,,,,Schwierigkeitsgrad,,,,,,,,,,,,,,,,, +About Demolition,MNU_ENGINECREDITS,,,,,Ãœber Demolition,,,,,,,,,,,,,,,,, +Press Y or N.,PRESSYN,,,,Stiskni Y nebo N.,Drücke Y oder N.,"Πάτα Y ή N +",Premu Y aÅ­ N.,Presiona Y ó N.,,Paina Y tai N.,Appuyez sur Y ou N.,Nyomj Y-t vagy N-t.,Premi Y oppure N.,Yã‹Nã§ç­”ãˆã‚,Y키 ë˜ëŠ” N키를 누르시오.,Druk op Y of N.,WciÅ›nij Y lub N.,Aperte Y ou N.,Carrega Y ou N.,,Ðажмите Y или N.,ПритиÑните Y или N. +"You can't save if you aren't playing! + +Press a key.",SAVEDEAD,,,,"NemůžeÅ¡ ukládat pokud nehrajeÅ¡! + +Stiskni libovolnou klávesu.","Du kannst nicht speichern, wenn du nicht spielst. + +Drücke eine Taste",,"Vi ne povas konservi, kiam vi ne ludas! + +Premu klavon.","¡No puedes guardar si no estás jugando! + +Presiona una tecla.",,"Et voi tallentaa, jos et ole pelissä! + +Paina jotain näppäintä.","Vous ne pouvez pas sauvegarder si vous ne jouez pas! + +Appuyez sur une touche.","Nem tudsz menteni ha nem is játszol! + +Nyomj meg egy gombot.","Non puoi salvare se non stai giocando! + +Premi un tasto.","プレイ中ã§ãªã„ã¨ã‚»ãƒ¼ãƒ–ã§ããªã„! + +何ã‹ã‚­ãƒ¼ã‚’押ã›","ê²Œìž„ì„ í”Œë ˆì´ ì¤‘ì´ì§€ ì•Šì„ ë•ŒëŠ” ê²Œìž„ì„ ì €ìž¥í•  수 없습니다! + +키를 누르시오.","Je kunt niet opslaan als je niet speelt! + +Druk op een toets.","Nie możesz zapisać, jeÅ›li nie grasz! + +WciÅ›nij dowolny klawisz.","Você não pode salvar se não estiver jogando! + +Aperte qualquer tecla.","Você não pode salvar se não estiver a jogar! + +Carrega numa tecla qualquer.",,"Ðевозможно Ñохранить игру, не начав её! + +Ðажмите любую клавишу.","Ðе можете Ñачувати игру ако не играте! + +ПритиÑните таÑтер." +Do you really want to do this?,SAFEMESSAGE,,,,VážnÄ› to chceÅ¡ udÄ›lat?,Möchtest du das wirklich tun?,,Ĉu vi vere volas fari tion?,¿Realmente quieres hacer esto?,¿Realmente quieres hacerlo?,Haluatko varmasti tehdä tämän?,Voulez-vous vraiment faire ça?,Biztos megakarod tenni?,Sei sicuro di volerlo fare?,本当ã«å®Ÿè¡Œã™ã‚‹ã®ã‹?,ì •ë§ë¡œ 정하시겠습니까?,Wil je dit echt doen?,NaprawdÄ™ chcesz to zrobić?,Você deseja mesmo fazer isso?,Desejas mesmo fazer isso?,,Ð’Ñ‹ уверены?,Да ли заиÑта желите то да урадите? +Not set,NOTSET,,,,Není nastavené,Nicht gesetzt,,Ne agordita,No Asignado,,Ei asetettu,Pas paramétré,Nincs beállítva,Non assegnato,セットã•ã‚Œã¦ãªã„,정하지 ì•ŠìŒ,Niet ingesteld,Nie ustawiono,Não definido,,,Ðе задан,Ðије намештено +"Quicksave over your game named + +'%s'? + +Press Y or N.",QSPROMPT,,,,"Rychle uložit pÅ™es tvoji hru s názvem + +'%s'? + +Stiskni Y nebo N.","Ãœberschreibe %s mit einem Schnellspeicherspielstand? + +Drücke Y oder N.",,"Ĉu rapidkonservu super via ludo, ke nomita + +'%s'? + +Premu Y aÅ­ N.","¿Deseas guardar sobre tu partida llamada + +'%s'? + +Presiona Y ó N.",,"Haluatko tallentaa pelin %s päälle? + +Paina Y tai N.","Sauvegarde rapide sur le fichier + +'%s'? + +Appuyez sur Y ou N.","Gyorsmenteni akarsz az alábbi mentésed alatt + +'%s'? + +Nyomj Y-t vagy N-t.","Sovrascrivere il salvataggio + +'%s'? + +Premi Y oppure N.","ã“ã®åå‰ã§ä¸Šæ›¸ãã™ã‚‹ã®ã‹? + +'%s' + +Y ã‹ N ã§ç­”ãˆã‚","빠른 ì €ìž¥ì„ í•˜ì‹œê² ìŠµë‹ˆê¹Œ? + +'%s' + +Y키 ë˜ëŠ” N키를 누르시오.","Snel opslaan over je spel genaamd + +'%s'? + +Druk op Y of N.","Szybko nadpisać grÄ™ + +„%sâ€? + +WciÅ›nij Y lub N.","Salvar sobre seu jogo chamado + +'%s'? + +Aperte Y ou N.","Gravar sobre o seu jogo chamado + +'%s'? + +Carrega Y ou N.",,"ПерезапиÑать быÑтрое Ñохранение + +«%s»? + +Ðажмите Y или N.","Желите брзо чување за игру под именом + +„%s“? + +ПритиÑните Y или N." +"Do you want to quickload the game named + +'%s'? + +Press Y or N.",QLPROMPT,,,,"PÅ™ejeÅ¡ si rychle naÄíst hru s názvem + +'%s'? + +Stiskni Y nebo N.","Möchtest du den Spielstand %s schnellladen? + +Drücke Y oder N.",,"Ĉu vi volas rapidÅargi la ludon, ke nomita + +'%s'? + +Premu Y aÅ­ N.","¿Quieres cargar la partida llamada + +'%s'? + +Presiona Y ó N.",,"Haluatko pikaladata pelin %s? + +Paina Y tai N.","Voulez-vous charger la sauvegarde + +'%s'? + +Appuyez sur Y ou N.","Gyorstölteni akarod ezt a mentést + +'%s'? + +Nyomj Y-t vagy N-t.","Vuoi fare un quickload della partita + +'%s'? + +Premi Y oppure N.","ã“ã®åå‰ã®ãƒ‡ãƒ¼ã‚¿ã‚’ロードã™ã‚‹ã®ã‹? + +'%s' + +Y ã‹ N ã§ç­”ãˆã‚","빠른 불러오기를 하시겠습니까? + +'%s' + +Y키 ë˜ëŠ” N키를 누르시오.","Wil je het spel snel laden met de naam + +'%s'? + +Druk op Y of N.","Czy chcesz wczytać szybki zapis + +„%sâ€? + +WciÅ›nij Y lub N.","Deseja carregar o jogo chamado + +'%s'? + +Aperte Y ou N.","Deseja carregar o jogo chamado + +'%s'? + +Carrega Y ou N.",,"Загрузить быÑтрое Ñохранение + +«%s»? + +Ðажмите Y или N.","Желите брзо учитавање за игру под именом + +„%s“? + +ПритиÑните Y или N." +Yes,TXT_YES,,,,Ano,Ja,Îαι,Jes,Sí,,Kyllä,Oui,Igen,Si,ã¯ã„,네,Ja,Tak,Sim,,,Да,Да +No,TXT_NO,,,,Ne,Nein,Όχι,Ne,No,,Ei,Non,Nem,No,ã„ã„ãˆ,아니요,Nee,Nie,Não,,,Ðет,Ðе +,,Savegame,,,,,,,,,,,,,,,,,,,,, +Empty slot,EMPTYSTRING,,,,Prázdný slot,nicht belegt,,Malplena Ingo,Ranura Vacía,,Tyhjä lokero,Emplacement Vide,Ãœres,Slot libero,空ãスロット,빈 슬롯,Lege sleuf,Puste miejsce,Vazio,,,ПуÑтой Ñлот,Празни Ñлот +,NEWSAVE,,,,,,,,,,,,<Új mentés>,,<æ–°è¦ã‚»ãƒ¼ãƒ–>,<새로운 게임 저장>,,,,,,<Ðовое Ñохранение>,<Ðова Ñачувана игра> +Game saved.,GGSAVED,,,,Hra uložena.,Spielstand gespeichert.,,Ludo konservita.,Partida guardada.,,Peli tallennettu.,Partie sauvegardée.,Játék mentve.,Gioco salvato.,セーブ完了。,ê²Œìž„ì´ ì €ìž¥ë¨.,Spel opgeslagen.,Gra zapisana.,Jogo salvo.,Jogo gravado.,,Игра Ñохранена.,Игра Ñачувана. +Time,SAVECOMMENT_TIME,,,,ÄŒas,Zeit,,Tempo,Tiempo,,Aika,Temps,IdÅ‘,Tempo,"時間 +",시간,Tijd,Czas,Tempo,,,ВремÑ,Време +Load Game,MNU_LOADGAME,,,,NaÄíst hru,Spiel laden,,ÅœarÄi Ludon,Cargar Partida,,Lataa peli,Chargement,,Carica gioco,ロード,게임 불러오기,Laden spel,Wczytaj GrÄ™,Carregar,,,Загрузка,Учитај игру +Save Game,MNU_SAVEGAME,,,,Uložit hru,Spiel sichern,,Konservi Ludon,Guardar Partida,,Tallenna peli,Sauvegarde,,Salva gioco,セーブ,게임 저장하기,Opslaan spel,Zapisz GrÄ™,Salvar,Gravar,,Сохранение,Сачувај игру +No Picture,MNU_NOPICTURE,,,,Bez obrázku,Kein Bild,,Neniu Bildo,Sin Imagen,,Ei kuvaa,Pas d'image,,Nessuna immagine,ç”»åƒç„¡ã—,사진 ì—†ìŒ,Geen beeld,Brak obrazka,Sem imagem,,,"Ðет +изображениÑ",Ðема Ñлике +"Different +Version",MNU_DIFFVERSION,,,,Jiná verze,Falsche Version,,Malsama Versio,Versión Diferente,,Eri versio,"Version +Différente",,Versione differente,"別ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® +データ",다른 버젼,Anders Versie,"Inna +Wersja","Versão +Diferente",,,"Ð”Ñ€ÑƒÐ³Ð°Ñ +верÑиÑ",Другачија верзија +No files,MNU_NOFILES,,,,Žádné soubory,Keine Dateien,,Neniuj dosieroj,Sin archivos,,Ei tiedostoja,Pas de fichiers,,Nessun file,ファイル無ã—,íŒŒì¼ ì—†ìŒ,Geen bestanden,Brak plików,Vazio,,,Ðет файлов,Ðема фајлова +"Do you really want to delete the savegame +",MNU_DELETESG,,,,Opravdu chceÅ¡ smazat tuto uloženou hru?,Willst du diesen Spielstand wirklich löschen?,,Ĉu vi vere volas forviÅi la konservan ludon?,"¿Realmente deseas eliminar la partida? +",,Haluatko varmasti poistaa tallennetun pelin ,"Voulez vous vraiment effacer cette sauvegarde? +",Biztos ki akarod törölni a mentést?,Vuoi veramente rimuovere il salvataggio,本当ã«ã“ã®ã‚»ãƒ¼ãƒ–を消ã™ã®ã‹?,ì €ìž¥ëœ ê²Œìž„ì„ ì •ë§ë¡œ 삭제하시겠습니까?,Wil je echt de opgeslagen spel verwijderen?,Czy naprawdÄ™ chcesz usunąć zapis gry,"Deseja mesmo deletar o jogo salvo +",Deseja mesmo apagar o jogo,,"Ð’Ñ‹ дейÑтвительно хотите удалить Ñохранение +",Да ли Ñтварно желите да избришете Ñачувану игру +,,,,,,,,,,,,,,,,,,,,,,, +Off,OPTVAL_OFF,,,,Vyp,Aus,,Malaktiva,Desactivado,,Pois,,,Disattivo,オフ,ë”,Uit,WyÅ‚Ä…czone,Desligado,,,Откл.,ИÑкљ. +On,OPTVAL_ON,,,,Zap,An,,Aktiva,Activado,,Päällä,,,Attivo,オン,켬,Aan,WÅ‚Ä…czone,Ligado,,,Вкл.,Укљ. +Auto,OPTVAL_AUTO,,,,,,,AÅ­tomata,Automático,,Automaattinen,,,Automatico,自動,ìžë™,,Automatycznie,Automático,,,Ðвто,ÐутоматÑки +Options,OPTMNU_TITLE,,,,Možnosti,Optionen,,Agordoj,Opciones,,Asetukset,Options,Beállítások,Opzioni,オプション,설정,Opties,Opcje,Opções,,,ÐаÑтройки,Подешавања +Customize Controls,OPTMNU_CONTROLS,,,,Nastavení ovládání,Steuerung einstellen,,Agordi Regilojn,Personalizar Controles,,Ohjausasetukset,Modifier les Contrôles,Irányítás testreszabása,Personalizza i controlli,キーé…置変更,ì¡°ìž‘ ì‚¬ìš©ìž ì§€ì •,Instellen van de controle,Ustaw Klawisze,Configurar Controles,Configurar Controlos,,Управление,Контроле +Mouse Options,OPTMNU_MOUSE,,,,Nastavení myÅ¡i,Mauseinstellungen,,Musagordoj,Opciones de Ratón,,Hiiriasetukset,Options de la Souris,Egér beállítások,Opzioni Mouse,マウス オプション,마우스 설정,Muis opties,Opcje Myszki,Opções de mouse,Opções do rato,,Мышь,Миш +Controller Options,OPTMNU_JOYSTICK,,,,Nastavení ovladaÄe,Joystickeinstellungen,,Ludregilagordoj,Opciones de Mando,,Peliohjainasetukset,Options de la Manette,JátékvezérlÅ‘ beállítások,Opzioni Joystick,コントローラーオプション,ì¡°ì´ìŠ¤í‹± 설정,Controller opties,Opcje Kontrolera,Opções de joystick,,,Контроллер,Контролер +Player Setup,OPTMNU_PLAYER,,,,Nastavení hráÄe,Spieler einrichten,,Ludanta Agordaĵo,Config. del Jugador,,Pelaaja-asetukset,Options du Joueur,Játékos testreszabása,Settaggio giocatore,プレイヤーã®ç‰¹å¾´,플레ì´ì–´ 설정,Speler instellen,Ustawienia Gracza,Configurações de Jogador,Configurações do Jogador,,Игрок,Играч +Gameplay Options,OPTMNU_GAMEPLAY,,,,Nastavení herních mechanik,Spieleinstellungen,,Ludadagordoj,Opciones de Jugabilidad,,Pelattavuusasetukset,Options du Gameplay,Játék mechanika,Opzioni Gameplay,ゲームプレイ オプション,게임 설정,Gameplay-opties,Opcje Rozgrywki,Opções de jogabilidade,,,Геймплей,Гејмплеј +Automap Options,OPTMNU_AUTOMAP,,,,Nastavení automapy,Automapeinstellungen,,AÅ­tomapagordoj,Opciones del Automapa,,Automaattikartan asetukset,Options de la Carte,Térkép beállítások,Opzioni Automappa,オートマップ オプション,오토맵 설정,Automap-opties,Opcje Mapy,Opções de automapa,,,Ðвтокарта,Ðутомапа +HUD Options,OPTMNU_HUD,,,,Nastavení HUD,HUD Einstellungen,,Agordoj de HUD,Opciones del HUD,,Tilanäytön asetukset,Options de l'ATH,HUD beállítások,Opzioni HUD,HUD オプション,HUD 설정,HUD opties,Opcje Paska HUD,Opções de HUD,,,HUD,HUD +Miscellaneous Options,OPTMNU_MISCELLANEOUS,,,,Ostatní nastavení,Verschiedene Einstellungen,,Ekstraĵagordoj,Opciones Misceláneas,,Sekalaiset asetukset,Options Annexes,Ãltalános beállítások,Opzioni miste,ãã®ä»–ã®ã‚ªãƒ—ション,ê·¸ 외 설정,Diverse opties,Różne Opcje,Outras opções,,,Дополнительно,Разно +Sound Options,OPTMNU_SOUND,,,,Nastavení zvuku,Soundeinstellungen,,Sonagordoj,Opciones de Sonido,,Ääniasetukset,Options du Son,Hang beállítások,Opzioni Suono,サウンド オプション,ìŒí–¥ 설정,Geluidsopties,Opcje DźwiÄ™ku,Opções de som,,,Звук,Звук +Display Options,OPTMNU_DISPLAY,,,,Nastavení grafiky,Anzeigeeinstellungen,,Ekranagordoj,Opciones de Visualización,,Näyttöasetukset,Options de l'Affichage,Megjelenítés beállítások,Opzioni Display,ディスプレイ オプション,ë””ìŠ¤í”Œë ˆì´ ì„¤ì •,Weergaveopties,Opcje WyÅ›wietlania,Opções de vídeo,,,Экран,Приказ +Set video mode,OPTMNU_VIDEO,,,,Nastavit režim displeje,Videomodus,,Agordi videoreÄimon,Modos de Vídeo,,Aseta videotila,Choisir Mode D'Affichage,Felbontás,Settaggio modalità video,ビデオ 調整,화면 설정,Videomodus instellen,Ustaw tryb wideo,Definir modo de vídeo,,,Видеорежим,Видео мод +Reset to defaults,OPTMNU_DEFAULTS,,,,Obnovit původní,Auf Vorgaben zurücksetzen,,ReÅanÄi al defaÅ­ltoj,Valores por Defecto,,Palauta oletusasetukset,Réinitialiser les paramètres,Alapértelmezett beállítások használata,Reimposta ai valori di default,åˆæœŸè¨­å®šã«æˆ»ã™,초기화,Terugzetten naar standaardinstellingen,Resetuj do domyÅ›lnych,Redefinir para configurações padrão,,,СброÑить вÑе наÑтройки,Врати подразумевано +Reset to last saved,OPTMNU_RESETTOSAVED,,,,Obnovit naposledy uložené,Auf gespeicherte Werte zurücksetzen,,ReÅanÄi al lasta konservo,Últimos Valores Guardados,,Palauta viimeksi tallennettu tila,Recharger dernière config.,Legutóbbi mentett beállítások használata,Reimposta ai valori salvati l'ultima volta,最後ã«ä¿å­˜ã—ãŸè¨­å®šã«æˆ»ã™,ì´ì „ 설정으로 초기화,Reset naar laatste opgeslagen,Resetuj do ostatnio zapisanych,Redefinir para última configuração salva,Redefinir para última configuração gravada,,Вернуть предыдущие наÑтройки,Врати задње Ñачувано +Go to console,OPTMNU_CONSOLE,,,,Jít do konzole,Öffne Konsole,,Iri al konzolo,Ir a la consola,,Mene konsoliin,Ouvrir la console,Konzol megnyitása,Vai alla console,コンソールを開ã,콘솔로 ì´ë™,Ga naar de console,Przejdź do konsoli,Abrir console,Abrir consola,,Открыть конÑоль,Отвори конзолу +,Controls submenu,,,,,,,,,,,,,,,,,,,,,, +Default,CTRL_DEFAULT,,,,,Standard,,,,,,,,,,,,,,,,, +Classic,CTRL_CLASSIC,,,,,"Klassisch +",,,,,,,,,,,,,,,,, +Left-handed,CTRL_LEFTHANDED,,,,,Linkshändig,,,,,,,,,,,,,,,,, +Preferred control preset,CTRL_PRESET,,,,,Bevorzugter Steuerungsstandard,,,,,,,,,,,,,,,,, +Customize Controls,CNTRLMNU_TITLE,,,,Nastavení ovládání,Steuerung einstellen,,Agordi Regilojn,Personalizar Controles ,,Ohjausasetukset,Modifier contrôles,Irányítás testreszabása,Personalizza i controlli,キーé…置変更,ì¡°ìž‘ ì‚¬ìš©ìž ì§€ì •,Instellen van de controle,Ustaw Klawisze,Configurar Controles,Configurar Controlos,,ÐаÑтройки управлениÑ,Подешавања контрола +"ENTER to change, BACKSPACE to clear",CNTRLMNU_SWITCHTEXT1,,,,"ENTER pro zmÄ›nu, BACKSPACE pro smazání",ENTER: Editieren BACKSPACE: Löschen,,"ENTER klavo por ÅanÄi, BACKSPACE klavo por viÅi","ENTER para cambiar, BACKSPACE para limpiar",,"Aseta ENTERILLÄ, tyhjennä ASKELPALAUTTIMELLA","ENTREE pour changer, RET. ARRIERE pour effacer.","ENTER a változtatáshoz, BACKSPACE a törléshez","INVIO per modificare, BACKSPACE per ripulire",Enter ã§æ±ºå®šã€BackSpaceã§ç„¡åŠ¹åŒ–,"바꿀려면 ENTER키, 지울려면 BACKSPACE키를 누르시오","ENTER om te veranderen, BACKSPACE om te wissen.","ENTER by zmienić, BACKSPACE by wyczyÅ›cić","ENTER para alterar, BACKSPACE para limpar",,,"ENTER — изменить, BACKSPACE — очиÑтить","ENTER за промену, BACKSPACE за чишћење" +"Press new key for control, ESC to cancel",CNTRLMNU_SWITCHTEXT2,,,,"ZmáÄkni novou klávesu pro nastavení, ESC pro storno",Drücke eine Taste oder ESC um abzubrechen,,"Premi novan klavon por reakiri regilon, ESC por nuligi","Presiona una tecla para el control, ESC para cancelar",,"Valitse näppäin toiminnolle, ESC peruuttaa","Appuyez sur la nouvelle touche pour l'assigner, +Appuyez sur ECHAP pour annuler.","Nyomj meg egy gombot, ESC a törléshez","Premi un nuovo tasto per il controllo, ESC per cancellare","登録ã—ãŸã„キーを押ã™ã‹, Escã§ã‚­ãƒ£ãƒ³ã‚»ãƒ«","ëª…ë ¹ì„ ì–½ìœ¼ë ¤ë©´ 아무 키를, 취소는 ESC키를 누르시오","Druk op de nieuwe toets voor controle, ESC om te annuleren.","WciÅ›nij nowy przycisk by zmienić klawisz, ESC by anulować","Aperte a nova tecla para o comando, ESC para cancelar","Carrega a nova tecla para o comando, ESC para cancelar",,"Ðажмите клавишу управлениÑ, ESC Ð´Ð»Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹","ПритиÑните ново таÑтер за одређивање контроле, ESC за отказивање" +Controls,CNTRLMNU_CONTROLS,,,,Ovládání,Steuerung,,Regiloj,Controles,,Ohjaimet,Contrôles,Irányítás,Controlli,æ“作系統,ì¡°ìž‘,Bedieningselementen,Klawisze,Comandos,Controlos,,Управление,Контроле +Fire,CNTRLMNU_ATTACK,,,,StÅ™elba,Feuer,,Pafi,Fuego,,Tuli,Tirer,Tűz,Fuoco,æ’ƒã¤,공격,Vuur,StrzaÅ‚,Atirar,,,Ðтака,Ðападни +Secondary Fire,CNTRLMNU_ALTATTACK,,,,Sekundární stÅ™elba,Alternativfeuer,,Duaranga Pafi,Fuego secundario,,Vaihtoehtoistuli,Tir Secondaire,Másodlagos tüzelés,Fuoco secondario,セカンダリ,ë³´ì¡° 공격,Secundaire vuur,StrzaÅ‚ Alternatywny,Tiro Secundário,,,Ð’Ñ‚Ð¾Ñ€Ð¸Ñ‡Ð½Ð°Ñ Ð°Ñ‚Ð°ÐºÐ°,Секундарни напад +Alternative Weapon,CNTRLMNU_ALTWEAPON,,,,,Alternative Waffe,,,,,,,,,,,,,,,,, +Use / Open,CNTRLMNU_USE,,,,Použít / otevřít,Benutzen / Öffnen,,Uzi / Malfermi,Usar / Abrir,,Käytä / Avaa,Utiliser/Ouvrir,Használ / Ajtónyitás,Usa / Apri,é–‹ã / スイッãƒç­‰ä½¿ç”¨,사용/열기,Gebruik / Openen,Użyj / Otwórz,Usar / Abrir,,,ИÑпользовать/открыть,КориÑти / Отвори +Move forward,CNTRLMNU_FORWARD,,,,Pohyb vpÅ™ed,Vorwärts bewegen,,Movi anatÅ­e,Avanzar,,Liiku eteenpäin,Avancer,ElÅ‘re mozgás,Movimento in Avanti,å‰é€²,앞으로 ì´ë™,Voorwaarts bewegen,Idź do przodu,Mover para frente,,,Движение вперёд,Крећи Ñе напред +Move backward,CNTRLMNU_BACK,,,,Pohyb vzad,Rückwarts bewegen,,Movi malantaÅ­e,Retroceder,,Liiku taaksepäin,Reculer,Hátra mozgás,Movimento in Indietro,後退,뒤로 ì´ë™,Achteruit bewegen,Idź do tyÅ‚u,Mover para trás,,,Движение назад,Крећи Ñе уназад +Strafe left,CNTRLMNU_MOVELEFT,,,,Pohyb doleva,Nach links bewegen,,Flankmovi maldekstre,Moverse a la izquierda,,Astu sivuun vasemmalle,Aller à Gauche,Balra oldalazás,Movimento laterale a sinistra,左移動,왼쪽으로 ì´ë™,Verplaats naar links,Unik w lewo,Mover para a esquerda,,,Движение влево,Крећи Ñе лево +Strafe right,CNTRLMNU_MOVERIGHT,,,,Pohyb doprava,Nach rechts bewegen,,Flankmovi dekstre,Moverse a la derecha,,Astu sivuun oikealle,Aller à Droite,Jobbra oldalazás,Movimento laterale a destra,å³ç§»å‹•,오른쪽으로 ì´ë™,Verplaats naar rechts,Unik w prawo,Mover para a direita,,,Движение вправо,Крећи Ñе деÑно +Turn left,CNTRLMNU_TURNLEFT,,,,OtoÄení vlevo,Nach links drehen,,Turni maldekstre,Girar a la izquierda,,Käänny vasemmalle,Tourner à Gauche,Balra fordul,"Gira a sinistra +",左をå‘ã,왼쪽으로 회전,Draai naar links,Obróć siÄ™ w lewo,Girar para a esquerda,,,Поворот налево,Окрени Ñе лево +Turn right,CNTRLMNU_TURNRIGHT,,,,OtoÄení vpravo,Nach rechts drehen,,Turni dekstre,Girar a la derecha,,Käänny oikealle,Tourner à Droite,Jobbra fordul,Gira a destra,å³ã‚’å‘ã,오른쪽으로 회전,Draai naar rechts,Obróć siÄ™ w prawo,Girar para a direita,,,Поворот направо,Окрени Ñе деÑно +Quick Turn,CNTRLMNU_TURN180,,,,Rychlé otoÄení,Schnelle Drehung,,Rapida turno,Giro rápido,,Pikakäännös,Faire un 180,Megfordulás,Rotazione rapida,背後をå‘ã,빠른 회전,Snelle draai,NagÅ‚y Obrót,Giro rápido,,,БыÑтрый разворот,Брзи окрет +Jump,CNTRLMNU_JUMP,,,,Skok,Springen,,Salti,Saltar,,Hyppää,Sauter,Ugrás,Salta,ジャンプ,ì í”„,Springen,Skok,Pular,Saltar,,Прыжок,Скок +Crouch,CNTRLMNU_CROUCH,,,,Kleknutí,Ducken,,KaÅ­ri,Agacharse,,Kyyristy,S'accroupir (tenir),Guggolás,Abbassati,屈む,숙ì´ê¸°,Hurken,KucniÄ™cie,Agachar,,,ПриÑедание,Чучни +Crouch Toggle,CNTRLMNU_TOGGLECROUCH,,,,Zap. / Vyp. kleknutí,Ducken an/aus,,KaÅ­rbaskulo,Alternar agachado,,Kyyristymisen vaihtokytkin,S'accroupir (alterner),Guggolási kapcsoló,Toggle abbassamento,屈む切替,숙ì´ê¸° 토글,Hurken Toggle,WÅ‚Ä…cz / WyÅ‚Ä…cz kucniÄ™cie,Agachar (Liga/Desliga),,,СеÑÑ‚ÑŒ/вÑтать,Чучни (без држања) +Mouse look,CNTRLMNU_MOUSELOOK,,,,Pohled myší,Maus-Blick,,Musilregardo,Vista con ratón,,Hiirikatselu,Vue à la souris,Egérrel való nézelÅ‘dés,Modalità vista col mouse,マウス視点上下化,마우스 룩,Muis-look,RozglÄ…danie siÄ™ myszkÄ…,Vista com o mouse,Vista com o rato,,Обзор мышью,Гледај мишем +Mouse look toggle,CNTRLMNI_MLOOKTOGGLE,,,,,Maus-Blick umschalten,,,,,,,,,,,,,,,,, +Look up,CNTRLMNU_LOOKUP,Look doesn't change the aim! It only alters the view pitch,,,Pohled vzhůru,Nach oben schauen,,Rigardi supre,Mirar arriba,,Katso ylös,Regarder en haut,Felfele nézés,Guarda sopra,視点を上ã’ã‚‹,위로 보기,Kijk omhoog,Patrz w górÄ™,Olhar para cima,,,Смотреть вверх,Гледај горе +Look down,CNTRLMNU_LOOKDOWN,,,,Pohled dolů,Nach unten schauen,,Rigardi malsupre,Mirar abajo,,Katso alas,Regarder en bas,Lefele nézés,Guarda sotto,視点を下ã’ã‚‹,아래로 보기,Kijk naar beneden,Patrz w dół,Olhar para baixo,,,Смотреть вниз,Гледај доле +Aim up,CNTRLMNU_AIMUP,,,,,Nach oben zielen,,,,,,,,,,,,,,,,, +Aim down,CNTRLMNU_AIMDOWN,,,,,Nach unten zielen,,,,,,,,,,,,,,,,, +Look left,CNTRLMNU_LOOKLEFT,,,,,Nach links schauen,,,,,,,,,,,,,,,,, +Look right,CNTRLMNU_LOOKRIGHT,,,,,Nach rechts schauen,,,,,,,,,,,,,,,,, +Center view,CNTRLMNU_CENTERVIEW,,,Centre view,VystÅ™edit pohled,Ansicht zentrieren,,Centra vidon,Centrar vista,,Keskitä katse,Recentrer Vue,Nézet középreigazítása,Sguardo centrato,視点を戻ã™,중앙 ì‹œì ìœ¼ë¡œ 보기,Middenaanzicht,WyÅ›rodkuj widok,Olhar para o centro,,,Отцентрировать взглÑд,Централизирај поглед +Run,CNTRLMNU_RUN,,,,BÄ›h,Rennen,,Kuri,Correr,,Juokse,Courir (tenir),Futás,Corri,駆ã‘足,달리기,Rennen,Bieg,Correr,,,Бег,Трчи +Toggle Run,CNTRLMNU_TOGGLERUN,,,,Zap. / Vyp. bÄ›h,Rennen an/aus,,Baskulkuri,Alternar Correr,,Juoksun vaihtokytkin,Courir (alterner),Futás kapcsoló,Toggle corsa,常時駆ã‘足切替,달리기 토글,Rennen aan/uit,WÅ‚Ä…cz / WyÅ‚Ä…cz bieg,Correr (Liga/Desliga),,,Бежать/идти,Трчи (без држања) +Strafe,CNTRLMNU_STRAFE,,,,Pohyb vlevo/vpravo,Seitwärts,,Flankmovi,Desplazamiento,,Astu sivuttain,Pas de côté,,Spostamento laterale,横移動化,양옆으로 ì´ë™,Zijdelings bewegen,Uniki,Deslocamento lateral,,,Движение боком,Кретање у Ñтрану +Show Scoreboard,CNTRLMNU_SCOREBOARD,,,,Zobrazit tabulku skóre,Punktetafel anzeigen,,Montri poentartabulon,Mostrar Marcador,,Näytä pistetaulu,Afficher Scores (tenir),EredményjelzÅ‘ megjelenítése,Mostra la tabella punteggio,スコアボード表示,ì ìˆ˜ì°½ 표시,Scorebord tonen,Pokaż tablicÄ™ wyników,Mostrar pontuação,,,Таблица очков,Табела +Action,CNTRLMNU_ACTION,,,,Akce,Aktion,,Ago,Acción,,Toiminta,,Akció,Azione,アクション,ë™ìž‘,Actie,Akcja,Ação,,,ОÑновное,Радња +Customize Action Controls,CNTRLMNU_ACTION_TITLE,,,,Nastavit ovládání akcí,Aktions-Steuerung einstellen,,Agordi Agajn Regilojn,Controles de Acción,,Toimintaohjausasetukset,Changer Contrôles Action,Akció beállítások testreszabása,Personalizza i controlli di azione,アクションæ“作設定,ì‚¬ìš©ìž ì§€ì • ë™ìž‘ 컨트롤,Aanpassen van de actiecontroles,Ustaw Klawisze Akcji,Configurar Comandos de Ação,Configurar Controlos de Ação,,ОÑновные клавиши управлениÑ,Контроле радње +Chat,CNTRLMNU_CHAT,,,,Chat,Chat,,Babilo,Chat,,Keskustelu,Chat,Chat,Chat,ãƒãƒ£ãƒƒãƒˆ,채팅,Chat,Czat,Chat,Conversar,,Чат,ЋаÑкање +Say,CNTRLMNU_SAY,,,,Říct,Reden,,Diro,Hablar,,Sano,Parler,Ãœzenet ,Parla,発言,채팅하기,Zeg,Powiedz,Fala,Falar,,Сообщение,Пиши +Customize Chat Controls,CNTRLMNU_CHAT_TITLE,,,,Nastavit ovládání chatu,Chat-Steuerung einstellen,,Agordi Babiladajn Regilojn,Controles de Chat,,Keskusteluohjausasetukset,Changer Contrôles Chat,Chat beállítások testreszabása,Personalizza i controlli della chat,ãƒãƒ£ãƒƒãƒˆæ“作設定,ì‚¬ìš©ìž ì§€ì • 채팅 컨트롤,Chat-controles aanpassen aan uw wensen,Ustaw Klawisze Czatu,Configurar Comandos de Chat,Configurar Controlos de Chat,,Клавиши ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‡Ð°Ñ‚Ð¾Ð¼,Контроле ћаÑкања +Customize Weapon Controls,CNTRLMNU_WEAPONS_TITLE,,,,Nastavit ovládání zbraní,Waffen-Steuerung einstellen,,Agordi Armilojn Regilojn,Controles de Armas,,Aseohjausasetukset,Changer Contrôles Armes,Fegyver beállítások testreszabása,Personalizza i controlli delle armi,武器æ“作設定,ì‚¬ìš©ìž ì§€ì • 무기 컨트롤,Wapencontroles aanpassen aan uw eigen wensen,Ustaw Klawisze Broni,Configurar Comandos de Arma,Configurar Controlos de Armas,,Клавиши ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ€ÑƒÐ¶Ð¸ÐµÐ¼,Контроле оружја +Customize Inventory Controls,CNTRLMNU_INVENTORY_TITLE,,,,Nastavit ovládání inventáře,Inventar-Steuerung einstellen,,Agordi Inventarajn Regilojn,Controles de Inventario,,Varusteohjausasetukset,Changer Contrôles Inventaires,Eszköztár beállítások testreszabása,Personalizza i controlli dell'inventario,インベントリæ“作設定,ì‚¬ìš©ìž ì§€ì • ì¸ë²¤í† ë¦¬ 컨트롤,Inventariscontroles aanpassen aan uw wensen,Ustaw Klawisze Ekwipunku,Configurar Comandos de Inventário,Configurar Controlos de Inventário,,Клавиши ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð½Ð²ÐµÐ½Ñ‚Ð°Ñ€Ñ‘Ð¼,Контроле Ñкладишта +Customize Other Controls,CNTRLMNU_OTHER_TITLE,,,,Nastavit ostatní ovládání,Sonstige Steuerung einstellen,,Agordi Ekstrajn Regilojn,Otros Controles,,Muut ohjausasetukset,Changer Autres Contrôles,Egyéb irányítás testreszabása,Personalizza altri controlli,ãã®ä»–ã®æ“作設定,ì‚¬ìš©ìž ì§€ì • ê·¸ 외 컨트롤,Andere bedieningselementen aanpassen,Ustaw Inne Klawisze,Configurar Outros Comandos,Configurar Outros Controlos,,Прочие клавиши,Друге контроле +Weapons,CNTRLMNU_WEAPONS,,,,ZbranÄ›,Waffen,,Armiloj,Armas,,Aseet,Armes,Fegyverek,Armi,武器,무기,Wapens,Bronie,Armas,,,Оружие,Оружје +Next weapon,CNTRLMNU_NEXTWEAPON,,,,Další zbraň,Nächste Waffe,,Proksima armilo,Arma siguiente,,Seuraava ase,Arme Suivante,KövetkezÅ‘ fegyver,Arma successiva,次ã®æ­¦å™¨,ë‹¤ìŒ ë¬´ê¸°,Volgende wapen,NastÄ™pna broÅ„,Próxima arma,,,Следующее оружие,Следеће оружје +Previous weapon,CNTRLMNU_PREVIOUSWEAPON,,,,PÅ™edchozí zbraň,Vorherige Waffe,,AntaÅ­a armilo,Arma anterior,,Edellinen ase,Arme Précédente,ElÅ‘zÅ‘ fegyver,Arma precedente,å‰ã®æ­¦å™¨,ì´ì „ 무기,Vorige wapen,Poprzednia broÅ„,Arma anterior,,,Предыдущее оружие,Претходно оружје +Weapon 1,CNTRLMNU_SLOT1,Todo - make game specific,,,Slot zbranÄ› 1,Waffe 1,,Armingo 1,Ranura de Arma 1,,Aselokero 1,Emplacement D'Arme 1,1. Fegyver,Slot arma 1,武器スロット 1,무기 슬롯 1,Wapenslot 1,BroÅ„ 1,Arma 1,,,Оружие 1,Оружје 1 +Weapon 2,CNTRLMNU_SLOT2,"only show appropriate slots per game +",,,Slot zbranÄ› 2,Waffe 2,,Armingo 2,Ranura de Arma 2,,Aselokero 2,Emplacement D'Arme 2,2. Fegyver,Slot arma 2,武器スロット 2,무기 슬롯 2,Wapenslot 2,BroÅ„ 2,Arma 2,,,Оружие 2,Оружје 2 +Weapon 3,CNTRLMNU_SLOT3,,,,Slot zbranÄ› 3,Waffe 3,,Armingo 3,Ranura de Arma 3,,Aselokero 3,Emplacement D'Arme 3,3. Fegyver,Slot arma 3,武器スロット 3,무기 슬롯 3,Wapenslot 3,BroÅ„ 3,Arma 3,,,Оружие 3,Оружје 3 +Weapon 4,CNTRLMNU_SLOT4,,,,Slot zbranÄ› 4,Waffe 4,,Armingo 4,Ranura de Arma 4,,Aselokero 4,Emplacement D'Arme 4,4. Fegyver,Slot arma 4,武器スロット 4,무기 슬롯 4,Wapenslot 4,BroÅ„ 4,Arma 4,,,Оружие 4,Оружје 4 +Weapon 5,CNTRLMNU_SLOT5,,,,Slot zbranÄ› 5,Waffe 5,,Armingo 5,Ranura de Arma 5,,Aselokero 5,Emplacement D'Arme 5,5. Fegyver,Slot arma 5,武器スロット 5,무기 슬롯 5,Wapenslot 5,BroÅ„ 5,Arma 5,,,Оружие 5,Оружје 5 +Weapon 6,CNTRLMNU_SLOT6,,,,Slot zbranÄ› 6,Waffe 6,,Armingo 6,Ranura de Arma 6,,Aselokero 6,Emplacement D'Arme 6,6. Fegyver,Slot arma 6,武器スロット 6,무기 슬롯 6,Wapenslot 6,BroÅ„ 6,Arma 6,,,Оружие 6,Оружје 6 +Weapon 7,CNTRLMNU_SLOT7,,,,Slot zbranÄ› 7,Waffe 7,,Armingo 7,Ranura de Arma 7,,Aselokero 7,Emplacement D'Arme 7,7. Fegyver,Slot arma 7,武器スロット 7,무기 슬롯 7,Wapenslot 7,BroÅ„ 7,Arma 7,,,Оружие 7,Оружје 7 +Weapon 8,CNTRLMNU_SLOT8,,,,Slot zbranÄ› 8,Waffe 8,,Armingo 8,Ranura de Arma 8,,Aselokero 8,Emplacement D'Arme 8,8. Fegyver,Slot arma 8,武器スロット 8,무기 슬롯 8,Wapenslot 8,BroÅ„ 8,Arma 8,,,Оружие 8,Оружје 8 +Weapon 9,CNTRLMNU_SLOT9,,,,Slot zbranÄ› 9,Waffe 9,,Armingo 9,Ranura de Arma 9,,Aselokero 9,Emplacement D'Arme 9,9. Fegyver,Slot arma 9,武器スロット 9,무기 슬롯 9,Wapenslot 9,BroÅ„ 9,Arma 9,,,Оружие 9,Оружје 9 +Weapon 10,CNTRLMNU_SLOT0,,,,Slot zbranÄ› 10,Waffe 10,,Armingo 0,Ranura de Arma 0,,Aselokero 0,Emplacement D'Arme 0,0. Fegyver,Slot arma 0,武器スロット 0,무기 슬롯 0,Wapenslot 0,BroÅ„ 10,Arma 0,,,Оружие 0,Оружје 0 +Inventory,CNTRLMNU_INVENTORY,,,,Inventář,Inventar,,Inventaro,Inventario,,Varusteet,Inventaire,Eszköztár beállítások testreszabása,Inventario,所æŒå“,ì¸ë²¤í† ë¦¬,Inventaris,Ekwipunek,Inventário,,,Инвентарь,Инвентар +Activate item,CNTRLMNU_USEITEM,,,,Aktivovat pÅ™edmÄ›t,Gegenstand aktivieren,,Aktivigi aĵon,Activar objeto,,Aktivoi varuste,Activer objet,Eszköz használata,Attiva oggetto,アイテムを使用,ì„ íƒí•œ ì•„ì´í…œ 사용,Item activeren,Użyj przedmiot,Ativar item,,,ИÑпользовать предмет,Ðктивирај предмет +Activate all items,CNTRLMNU_USEALLITEMS,,,,Aktivovat vÅ¡echny pÅ™edmÄ›ty,Alle Gegenstände aktivieren,,Aktivigi ĉiuj aĵojn,Activar todos los objetos,,Aktivoi kaikki varusteet,Activer tous les objets,Minden eszköz használata,Attiva tutti gli oggetti,å…¨ã¦ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’使用,모든 ì•„ì´í…œ 사용,Activeer alle items,Użyj wszystkie przedmioty,Ativar todos os itens,,,ИÑпользовать вÑе предметы,Ðктивирај Ñве предмете +Next item,CNTRLMNU_NEXTITEM,,,,Další pÅ™edmÄ›t,Nächster Gegenstand,,Proksima aĵo,Objeto siguiente,,Seuraava varuste,Objet suivant,KövetkezÅ‘ eszköz,Oggetto successivo,次ã®ã‚¢ã‚¤ãƒ†ãƒ ,ë‹¤ìŒ ì•„ì´í…œ,Volgende item,NastÄ™pny przedmiot,Próximo item,,,Следующий предмет,Следећи предмет +Previous item,CNTRLMNU_PREVIOUSITEM,,,,PÅ™edchozí pÅ™edmÄ›t,Vorheriger Gegenstand,,AntaÅ­a aĵo,Objeto anterior,,Edellinen varuste,Objet précédent,ElÅ‘zÅ‘ eszköz,Oggetto precedente,å‰ã®ã‚¢ã‚¤ãƒ†ãƒ ,ì´ì „ ì•„ì´í…œ,Vorige item,Poprzedni przedmiot,Item anterior,,,Предыдущий предмет,Претходни предмет +Holster Weapon,CNTRLMNU_HOLSTER,,,,,Waffe wegstecken,,,,,,,,,,,,,,,,, +Quick Kick,CNTRLMNU_QUICKKICK,,,,,Schneller Tritt,,,,,,,,,,,,,,,,, +Pee,CNTRLMNU_PEE,,,,,Pinkeln,,,,,,,,,,,,,,,,, +Proximity Bomb,CNTRLMNU_PROXIMITYBOMBS,,,,,,,,,,,,,,,,,,,,,, +Remote Bomb,CNTRLMNU_REMOTEBOMBS,,,,,,,,,,,,,,,,,,,,,, +Smoke Bomb,CNTRLMNU_SMOKEBOMB,,,,,Rauchbombe,,,,,,,,,,,,,,,,, +Gas Bomb,CNTRLMNU_GASBOMB,,,,,Gasgranate,,,,,,,,,,,,,,,,, +Flash Bomb,"CNTRLMNU_FLASHBOMB +",,,,,Blendgranate,,,,,,,,,,,,,,,,, +Caltrops,CNTRLMNU_CALTROPS,,,,,Krähenfüße,,,,,,,,,,,,,,,,, +Holo Duke,CNTRLMNU_HOLODUKE,,,,,,,,,,,,,,,,,,,,,, +Jetpack,CNTRLMNU_JETPACK,,,,,,,,,,,,,,,,,,,,,, +Night Vision,CNTRLMNU_NIGHTVISION,,,,,Nachtsichtgerät,,,,,,,,,,,,,,,,, +Medkit,CNTRLMNU_MEDKIT,,,,,,,,,,,,,,,,,,,,,, +Steroids,CNTRLMNU_STEROIDS,,,,,Steroide,,,,,,,,,,,,,,,,, +Holo Soldier,CNTRLMNU_HOLOSOLDIER,,,,,Holosoldat,,,,,,,,,,,,,,,,, +Huey,CNTRLMNU_HUEY,,,,,,,,,,,,,,,,,,,,,, +Bier,CNTRLMNU_BEER,,,,,Bier,,,,,,,,,,,,,,,,, +Cow Pie,CNTRLMNU_COWPIE,not translatable,,,,,,,,,,,,,,,,,,,,, +Yeehaa,CNTRLMNU_YEEHAA,not translatable,,,,,,,,,,,,,,,,,,,,, +Whiskey,CNTRLMNU_WHISKEY,,,,,Whisky,,,,,,,,,,,,,,,,, +Moonshine,CNTRLMNU_MOONSHINE,,,,,Schwarzgebrannter,,,,,,,,,,,,,,,,, +Crystal Ball,CNTRLMNU_CRYSTALBALL,,,,,Kristallkugel,,,,,,,,,,,,,,,,, +Jump Boots,CNTRLMNU_JUMPBOOTS,,,,,Sprungstiefel,,,,,,,,,,,,,,,,, +Beast Vision,CNTRLMNU_BEASTVISION,,,,,,,,,,,,,,,,,,,,,, +Tank Mode,CNTRLMNU_TANKMODE,,,,,Panzermodus,,,,,,,,,,,,,,,,, +Smokes,CNTRLMNU_SMOKES,What precisely is this?,,,,,,,,,,,,,,,,,,,,, +Fire Mission,CNTRLMNU_FIRE_MISSION,,,,,,,,,,,,,,,,,,,,,, +Reload,CNTRLMNU_RELOAD,,,,,"Waffe laden +",,,,,,,,,,,,,,,,, +Radar,CNTRLMNU_RADAR,,,,,,,,,,,,,,,,,,,,,, +Other,CNTRLMNU_OTHER,,,,Ostatní,Andere,,Alia,Otros,,Muu,Autres,Más,Altro,ãã®ä»–,ê·¸ 외 ì¡°ìž‘,Andere,Inne,Outro,,,Прочее,ОÑтало +Messages: OFF,MSGOFF,,,,Zprávy ZAP,Meldungen AUS,ΜηνÏματα ΚΛΕΙΣΤΑ,MesaÄoj MALAKTIVA,Mensajes DESACTIVADOS,,Viestit POIS PÄÄLTÄ,Messages désactivés.,Ãœzenetek KI,Messaggi DISATTIVATI,メッセージ: オフ,메시지 ë”,Berichten UIT,WiadomoÅ›ci WYÅÄ„CZONE,Mensagens DESATIVADAS,,,Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÐžÐ¢ÐšÐ›Ð®Ð§Ð•ÐЫ,Поруке ИСКЉУЧЕÐЕ +Messages: ON,MSGON,,,,Zprávy VYP,Meldungen AN,ΜηνÏματα ΑÎΟΙΧΤΑ,MesaÄoj AKTIVA,Mensajes ACTIVADOS,,Viestit PÄÄLLÄ,Messages activés.,Ãœzenetek BE,Messaggi ATTIVATI,メッセージ: オン,메시지 켬,Berichten AAN,WiadomoÅ›ci WÅÄ„CZONE,Mensagens ATIVADAS,,,Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð’ÐšÐ›Ð®Ð§ÐÐЫ,Поруке УКЉУЧЕÐЕ +Writin': OFF,MSGOFF,,Redneck RedneckRides,,Zprávy ZAP,Geschreibsel: AUS,ΜηνÏματα ΚΛΕΙΣΤΑ,MesaÄoj MALAKTIVA,Mensajes DESACTIVADOS,,Viestit POIS PÄÄLTÄ,Messages désactivés.,Ãœzenetek KI,Messaggi DISATTIVATI,メッセージ: オフ,메시지 ë”,Berichten UIT,WiadomoÅ›ci WYÅÄ„CZONE,Mensagens DESATIVADAS,,,Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÐžÐ¢ÐšÐ›Ð®Ð§Ð•ÐЫ,Поруке ИСКЉУЧЕÐЕ +Writin': ON,MSGON,,Redneck RedneckRides,,Zprávy VYP,Geschreibsel: AN,ΜηνÏματα ΑÎΟΙΧΤΑ,MesaÄoj AKTIVA,Mensajes ACTIVADOS,,Viestit PÄÄLLÄ,Messages activés.,Ãœzenetek BE,Messaggi ATTIVATI,メッセージ: オン,메시지 켬,Berichten AAN,WiadomoÅ›ci WÅÄ„CZONE,Mensagens ATIVADAS,,,Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð’ÐšÐ›Ð®Ð§ÐÐЫ,Поруке УКЉУЧЕÐЕ +Mouse aiming ON,TXT_MOUSEAIMON,,,,,Maus-Blick AN,,,,,,,,,,,,,,,,, +Mouse aiming OFF,TXT_MOUSEAIMOFF,,,,,Maus-Blick AUS,,,,,,,,,,,,,,,,, +Rat aimin' ON,TXT_MOUSEAIMON,I don't think this translates well...,Redneck RedneckRides,,,Maus-Blick AN,,,,,,,,,,,,,,,,, +Rat aimin' OFF,TXT_MOUSEAIMOFF,,Redneck RedneckRides,,,Maus-Blick AUS,,,,,,,,,,,,,,,,, +Toggle automap,CNTRLMNU_AUTOMAP,,,,Zap. / Vyp. automapu,Automap an/aus,,Baskuligi aÅ­tomapo,Alternar automapa,,Kytke automaattikartta päälle/pois,Activer Carte,Térkép ki- bekapcsolása,Toggle automappa,オートマップã®åˆ‡æ›¿,오토맵 ì¡°ì •,Automap aan/uit,WÅ‚Ä…cz mapÄ™,Ativar automapa,,,Открыть автокарту,Прикажи аутомапу +Chasecam,CNTRLMNU_CHASECAM,,,,Kamera z tÅ™etí osoby,Verfolgerkamera,,Ĉaskamerao,Cámara de Seguimiento,,Seurantakamera,Caméra 3ième personne,KülsÅ‘nézetű kamera,Telecamera di inseguimento,背後視点,3ì¸ì¹­ ì¹´ë©”ë¼,,Kamera Åšledzenia,Câmera de terceira-pessoa,Câmera em terceira-pessoa,,Вид от 3-го лица (Chasecam),ЧејÑ-кем +Screenshot,CNTRLMNU_SCREENSHOT,,,,Pořídit snímek obrazovky,,,Ekranfoto,Captura de pantalla,,Kuvakaappaus,Capture d'écran,KépernyÅ‘ lefényképezése,Cattura schermo,ç”»é¢ã‚­ãƒ£ãƒ—ãƒãƒ£,스í¬ë¦°ìƒ·,,Zrzut ekranu,Captura de tela,,,Скриншот,УÑликај +Open console,CNTRLMNU_CONSOLE,,,,Otevřít konzoli,Konsole öffnen,,Malfermi konzolon,Abrir consola,,Avaa konsoli,Ouvrir Console,Konzol elÅ‘hozása,Apri la console,コンソールを開ã,콘솔 열기,Open console,Otwórz konsolÄ™,Abrir console,Abrir consola,,Открыть конÑоль,Отвори конÑолу +Pause,CNTRLMNU_PAUSE,,,,Pauza,,,PaÅ­zo,Pausa,,Tauko,,Szünet,Pausa,ãƒãƒ¼ã‚º,ì¼ì‹œì •ì§€,Pauze,Pauza,Pausa,,,Пауза,Пауза +Increase Display Size,CNTRLMNU_DISPLAY_INC,,,,ZvÄ›tÅ¡it velikost displeje,Anzeige vergrößern,,Pligrandigi Ekranamplekson,Agrandar Ventana,,Suurenna näytön kokoa,Agrandir l'affichage,Képméret növelése,Incrementa la dimensione del display,ç”»é¢ã‚µã‚¤ã‚ºã‚’拡大,화면 í¬ê¸° 늘리기,Vergroot het display,PowiÄ™ksz Rozmiar WyÅ›wietlania,Aumentar Tamanho de Tela,Aumentar Tamanho do Ecrã,,Увеличить размер Ñкрана,Повећајте величину екрана +Decrease Display Size,CNTRLMNU_DISPLAY_DEC,,,,ZmenÅ¡it velikost displeje,Anzeige verkleinern,,Plimalgrandigi Ekranamplekson,Reducir Ventana,,Pienennä näytön kokoa,Réduire l'affichage,Képméret csökkentése,Decrementa la dimensione del display,ç”»é¢ã‚µã‚¤ã‚ºã‚’縮å°,화면 í¬ê¸° 줄ì´ê¸°,Verlaag het display,Pomniejsz Rozmiar WyÅ›wietlania,Diminuir Tamanho de Tela,Diminuir Tamanho do Ecrã,,Уменьшить размер Ñкрана,Смањите величину екрана +Open Help,CNTRLMNU_OPEN_HELP,,,,Otevřít nápovÄ›du,Hilfe öffnen,,Malfermi Helpon,Abrir Ayuda,,Avaa ohje,Ouvrir Aide,Segítség elÅ‘hozása,Apri l'aiuto,"ヘルプを開ã +",ë„ì›€ë§ ì—´ê¸°,Open hulp,Otwórz Pomoc,Abrir Ajuda,,,Экран помощи,Отвори помоћ +Open Save Menu,CNTRLMNU_OPEN_SAVE,,,,Otevřít menu pro uložení,Speichermenü öffnen,,Malfermi Konservmenuon,Menú de Guardar Partida,,Avaa tallennusvalikko,Ouvrir Menu Sauvegarde,Mentés menü elÅ‘hozása,Apri il menu di salvataggio,セーブメニューを開ã,저장 화면 열기,Menu opslaan openen,Otwórz Menu Zapisu,Abrir Menu de Salvar,Abrir Menu de Gravação,,Сохранение игры,Отвори Ñачуване игре +Open Load Menu,CNTRLMNU_OPEN_LOAD,,,,Otevřít menu pro naÄtení,Lademenü öffnen,,Malfermi ÅœarÄmenuon,Menú de Cargar Partida,,Avaa latausvalikko,Ouvrir Menu Chargement,Betöltés menü elÅ‘hozása,Apri il menu di caricamento,ロードメニューを開ã,불러오기 화면 열기,Menu laden openen,Otwórz Menu Wczytania,Abrir Menu de Carregar,,,Загрузка игры,Отвори игре за учитати +Open Options Menu,CNTRLMNU_OPEN_OPTIONS,,,,Otevřít nastavení,Optionsmenü öffnen,,Malfermi Agordmenuon,Menú de Opciones,,Avaa asetusvalikko,Ouvrir Menu Options,Beállítások menü elÅ‘hozása,Apri il menu delle opzioni,オプションメニューを開ã,설정 화면 열기,Menu Opties openen,Otwórz Menu Opcji,Abrir Menu de Opções,,,Главное меню наÑтроек,Отвори мени опција +Open Display Menu,CNTRLMNU_OPEN_DISPLAY,,,,Otevřít nastavení grafiky,Anzeigemenü öffnen,,Malfermi Ekranmenuon,Menú de Opciones de Visualización,,Avaa näyttövalikko,Ouvrir Menu Affichage,Megjelenítés menü elÅ‘hozása,Apri il menu del display,ディスプレイメニューを開ã,ë””ìŠ¤í”Œë ˆì´ í™”ë©´ 열기,Displaymenu openen,Otwórz Menu WyÅ›wietlania,Abrir Menu de Vídeo,,,Меню наÑтроек видео,Отвори мени приказа +Quicksave,CNTRLMNU_QUICKSAVE,,,,Rychlé uložení,Schnellspeichern,,Rapidkonservo,Guardado Rápido,,Pikatallenna,Sauv. Rapide,Gyorsmentés,Salvataggio rapido,クイックセーブ,빠른 저장,Snel opslaan,Szybki Zapis,Salvamento rápido,Gravação rápida,,БыÑтрое Ñохранение,Брзо-Ñачувај +Quickload,CNTRLMNU_QUICKLOAD,,,,Rychlé naÄtení,Schnellladen,,RapidÅarÄo,Cargado Rápido,,Pikalataa,Charg. Rapide,Gyors betöltés,Caricamento rapido,クイックロード,빠른 불러오기,Snel laden,Szybkie Wczytanie,Carregamento rápido,,,БыÑÑ‚Ñ€Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°,Брзо-учитај +Exit to Main Menu,CNTRLMNU_EXIT_TO_MAIN,,,,Odejít do hlavního menu,Zurück zum Hauptmenü,,Eliri al Ĉefa Menuo,Salir al Menú Principal,,Poistu päävalikkoon,Sortie Menu Principal,Kilépés a fÅ‘menübe,Esci dal menu principale,メインメニューã«æˆ»ã‚‹,메뉴로 나오기,Afsluiten naar het hoofdmenu,Wyjdź do Głównego Menu,Sair para o Menu Principal,,,Выход в главное меню,Изађи у главни мени +Toggle Messages,CNTRLMNU_TOGGLE_MESSAGES,,,,Zap. / Vyp. zprávy,Nachrichten an/aus,,Baskuligi MensaÄojn,Alternar Mensajes,,Kytke viestit päälle tai pois,Act./Déasct. Messages,Ãœzenetek kapcsololása,Toggle messaggi,メッセージ表示ã®åˆ‡æ›¿,메시지 토글,Berichten aan/uit,WÅ‚Ä…cz / WyÅ‚Ä…cz WiadomoÅ›ci,Ativar Mensagens,,,Переключение Ñообщений,Таглави поруке +Quit Game,CNTRLMNU_MENU_QUIT,,,,Odejít ze hry,Spiel beenden,,Ĉesigi Ludon,Salir del Juego,,Lopeta peli,Quitter le Jeu,Kilépés a játékból.,Esci dal gioco,ゲームを終了,게임 종료,Stop het spel,Wyjdź z Gry,Sair do Jogo,,,Выход,Изађи из игре +Adjust Gamma,CNTRLMNU_ADJUST_GAMMA,,,,Nastavit gamu,Gamma-Anpassung,,Agordi Gamaon,Ajustar Gamma,,Säädä gammaa,Ajuster Gamma,Gamma állítása,Aggiustamento Gamma,ガンマ値を調整,ê°ë§ˆ ì¡°ì •,Gamma aanpassen,Dostosuj GammÄ™,Ajustar Gama,,,ÐаÑтройка гаммы,ПодеÑите оÑветљење +Mouse Options,MOUSEMNU_TITLE,,,,Nastavení myÅ¡i,Mausoptionen,,Musilagordoj,Opciones del Ratón,,Hiiriasetukset,Options Souris,Egér beállítások,Opzioni Mouse,マウス オプション,마우스 설정,Muis opties,Opcje Myszki,Opções de mouse,Opções do rato,,ÐаÑтройки мыши,Миш +Enable mouse,MOUSEMNU_ENABLEMOUSE,,,,Povolit myÅ¡,Maus aktiv,,Aktivigi muson,Habilitar ratón,,Ota hiiri käyttöön,Activer Souris,Egér engedélyezése,Abilita il mouse,マウスã®ä½¿ç”¨,마우스 사용,Muis inschakelen,WÅ‚Ä…cz myszkÄ™,Habilitar mouse,Permitir uso do rato,,ИÑпользовать мышь,Укључи миш +Enable mouse in menus,MOUSEMNU_MOUSEINMENU,,,,Povolit myÅ¡ v nabídkách,Maus aktiv in Menüs,,Aktivigi muson en menuoj,Usa ratón en los menús,,Ota hiiri käyttöön valikoissa,Activer Souris dans les Menus,Egér engedélyezése a menüben.,Abilita il mouse nei menu,メニューã§ã®ãƒžã‚¦ã‚¹ã®ä½¿ç”¨,메뉴ì—ì„œ 마우스 사용,Muis in menu's inschakelen,WÅ‚Ä…cz myszkÄ™ w menu,Habilitar mouse nos menus,Permitir rato nos menus,,ИÑпользовать мышь в меню,Укључи миш у менијима +Show back button,MOUSEMNU_SHOWBACKBUTTON,,,,Zobrazit tlaÄítko zpÄ›t,Zeige Zurück-Knopf,,Montri antaÅ­klavon,Botón de retroceso,,Näytä taaksenäppäin,Afficher le bouton retour,Vissza gomb mutatása,Mostra il bottone per tornare indietro,戻るボタンを表示,뒤로가기 버튼 ë³´ì´ê¸°,Toon terug knop,Pokaż przycisk powrotu,Mostrar botão de voltar,,,РаÑположение кнопки «назад»,Прикажи таÑтер за назад +Cursor,MOUSEMNU_CURSOR,,,,Kurzor,,,Musmontrilo,,,Osoitin,Curseur,Egérmutató,Cursore,カーソル,커서,,Kursor,,,,КурÑор,КурÑор +Overall sensitivity,MOUSEMNU_SENSITIVITY,,,,Celková citlivost,Allgemeine Empfindlichkeit,,Tutsentemo,Sensibilidad promedio,,Yleinen herkkyys,Sensibilité générale,Teljes érzékenység,Sensibilità complessiva,全体的ãªæ„Ÿåº¦,ì „ì²´ 민ê°ë„,Algemene gevoeligheid,Ogólna wrażliwość,Sensibilidade geral,,,ÐžÐ±Ñ‰Ð°Ñ Ñ‡ÑƒÐ²ÑтвительноÑÑ‚ÑŒ,ОÑетљивоÑÑ‚ +Prescale mouse movement,MOUSEMNU_NOPRESCALE,,,,Akcelerace myÅ¡i,Mausbewegung skalieren,,AntaÅ­pesilo musmovo,Pre-escalar movimiento,,Esiskaalaa hiiren liike,Prescaling mouvement souris,,Prescala il movimento del mouse,マウスæ“作ã®ç²¾å¯†åŒ–,ì†ë„ ë†’ì¸ ì›€ì§ìž„,Muisbewegingen vooraf inschalen,Przeskaluj ruch myszki,Movimento pré-escalar do mouse,Movimento pré-escalar do rato,,Ð£Ð²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð½Ð°Ñ Ñ‡ÑƒÐ²ÑтвительноÑÑ‚ÑŒ,Убрзање миша +Smooth mouse movement,MOUSEMNU_SMOOTHMOUSE,,,,Vyhladit pohyb myÅ¡i,Mausbewegung glätten,,Glata musmovo,Mov. fluido del ratón,,Sulava hiiren liike,Lissage Souris,Egyenletes egérmozdulatok,Movimento del mouse liscio,マウスæ“作を滑らã‹ã«ã™ã‚‹,부드러운 움ì§ìž„,Vlotte muisbeweging,GÅ‚adki ruch myszki,Movimento fluído do mouse,Movimento fluído do rato,,Плавное перемещение,Глатки окрет +Turning speed,MOUSEMNU_TURNSPEED,,,,Rychlost otáÄení,Umdrehgeschwindigkeit,,Turnorapido,Velocidad de giro,,Kääntymisnopeus,Vitesse pour tourner,Fordulási sebesség,Velocità di rotazione,旋回速度,회전 ì†ë„,Draaisnelheid,Szybkość obracania siÄ™,Velocidade de giro,,,СкороÑÑ‚ÑŒ поворота,Брзина окрета +Mouselook speed,MOUSEMNU_MOUSELOOKSPEED,,,,Rychlost pohledu nahoru/dolů,Mausblick-Geschwindigkeit,,Musrigarda rapido.,Veloc. de vista con ratón,,Katselunopeus,Vitesse Vue Souris,Egérrel való nézés sebessége,Velocità di rotazione della vista,上下視点速度,마우스룩 ì†ë„,Mouselook snelheid,Szybkość rozglÄ…dania siÄ™ myszkÄ…,Velocidade de vista com mouse,Velocidade de vista com rato,,СкороÑÑ‚ÑŒ обзора,Брзина гледања мишем +Forward/Backward speed,MOUSEMNU_FORWBACKSPEED,,,,Rychlost pohybu vpÅ™ed/vzad,Vor/Rückwärtsgeschwindigkeit,,AntaÅ­a/MalantaÅ­a rapido,Veloc. de avance/retroceso,,Eteen-/taaksepäin liikkeen nopeus,Vitesse Avancer/reculer,ElÅ‘re/Hátra sebesség,Velocità avanti/indietro,"å‰é€²/後退速度 +",전진/후진 ì†ë„,Voorwaartse/achterwaartse snelheid,Szybkość chodzenia do przodu/do tyÅ‚u,Velocidade de deslocamento para frente/trás,,,СкороÑÑ‚ÑŒ передвижениÑ,Брзина окрета напред/уназад +Strafing speed,MOUSEMNU_STRAFESPEED,,,,Rychlost pohybu do stran,Seitwärtsgeschwindigkeit,,Flankmova rapido,Veloc. de mov. lateral,,Sivuttaisastunnan nopeus,Vitesse Gauche/Droite,,Velocità movimento laterale,横移動速度,좌진/우진 ì†ë„,Zijdelings snelheid,Szybkość uników,Velocidade de deslocamento lateral,,,СкороÑÑ‚ÑŒ Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð±Ð¾ÐºÐ¾Ð¼,Брзина Ñтрејфа +Always Mouselook,MOUSEMNU_ALWAYSMOUSELOOK,,,,Vždy se rozhlížet myší,Mausblick immer an,,Ĉiam Musrigardo,Siempre mirar con ratón,,Jatkuva hiirikatselu,Toujours vue Souris,Mindig nézelÅ‘dés az egérrel,Vista col mouse,常ã«ä¸Šä¸‹è¦–点をオン,마우스룩 사용,Altijd Mouselook,Zawsze zezwalaj na rozglÄ…danie siÄ™ myszkÄ…,Vista com mouse sempre ligado,Vista com rato sempre ligada,,Обзор мышью,Гледање мишем +Invert Mouse,MOUSEMNU_INVERTMOUSE,,,,Inverzní myÅ¡,Maus invertieren,,Inversa Muso,Invertir ratón,,Käännä hiiri,Inverser Souris,Egérirányok megfordítása,Mouse invertito,視点æ“作å転,마우스 ë°©í–¥ 전환,Muis omkeren,Odwróć MyszkÄ™,Inverter mouse,Inverter rato,,Инвертирование мыши,Инвертуј миш +Mouselook Toggle,MOUSEMNU_LOOKSPRING,,,,Automatické vystÅ™edÄ›ní pohledu,Automatisch zentrieren,,Rigardsalto,Mirar con ratón,,Katseenpalautin,Recentrer après Vue Souris,,,視点水平化,마우스룩 ì‹œì  ì´ˆê¸°í™”,Lente,Automatyczne WyÅ›rodkowanie,Centralizar automáticamente,Centrar automáticamente,,Передвижение мышью,Покрет мишем +Mouse Strafe,MOUSEMNU_LOOKSTRAFE,,,,Použít myÅ¡ k pohybu do stran,Seitwärts bewegen mit der Maus,,Rigardturnmovo,Mirar con movimiento,,Sivuttaisastuntapalautin,Mouvement Latéral par Souris,,,視点横移動化,마우스룩 좌우 ì´ë™,Lookstrafe,Unikanie przy użyciu myszki,Deslocamento lateral com o mouse,Deslocamento lateral com o rato,,Движение боком мышью,Стрејф мишем +Upper left,OPTVAL_UPPERLEFT,,,,Vlevo nahoÅ™e,Oben links,,Supra maldekstre,Sup. izquierda,,Ylävasemmalla,Supérieur gauche,,Superiore sinistro,左上,왼쪽 위,Linksboven,Lewy górny róg,Esquerda superior,,,Вверху Ñлева,Горње лево +Upper right,OPTVAL_UPPERRIGHT,,,,Vpravo nahoÅ™e,Oben rechts,,Supra dekstre,Sup. derecha,,Yläoikealla,Supérieur droite,,Superiore destro,å³ä¸Š,오른쪽 위,Rechtsboven,Prawy górny róg,Direita superior,,,Вверху Ñправа,Горње деÑно +Lower left,OPTVAL_LOWERLEFT,,,,Vlevo dole,Unten links ,,Suba maldekstre,Inf. izquierda,,Alavasemmalla,Inférieur gauche,,Inferiore sinistro,左下,왼쪽 ë°‘,Linksonder,Lewy dolny róg,Esquerda inferior,,,Внизу Ñлева,Доње лево +Lower right,OPTVAL_LOWERRIGHT,,,,Vpravo dole,Unten rechts,,Suba dekstre,Inf. derecha,,Alaoikealla,Inférieur droite,,Inferiore destro,å³ä¸‹,오른쪽 ë°‘,Rechtsonder,Prawy dolny róg,Direita inferior,,,Внизу Ñправа,Доње деÑно +Touchscreen-like,OPTVAL_TOUCHSCREENLIKE,,,,Jako dotyková obrazovka,Wie auf einem Touchscreen,,TuÅekrana,Pant. táctil,,Kosketusnäyttömäinen,Style écran tactile,,Come il Touchscreen,タッãƒã‚¹ã‚¯ãƒªãƒ¼ãƒ³å¼,터치스í¬ë¦° 같게,Touchscreen-achtige,Jak ekrean dotykowy,Estilo touchscreen,,,Как ÑенÑорный Ñкран,Као додирни екран +Simple arrow,OPTSTR_SIMPLEARROW,,,,Jednoduchý kurzor,Einfacher Pfeil,,Simpla sago,Flecha simple,,Yksinkertainen nuoli,Flèche simple,,Freccia semplice,シンプル,기본 커서,Eenvoudige pijl,Prosta strzaÅ‚ka,Flecha simples,Cursor simples,,Стрелка,Стрелица +System cursor,OPTSTR_SYSTEMCURSOR,,,,Systémový kurzor,Systemcursor,,Sistema kursoro,Cursor del sistema,,Järjestelmän osoitin,Curseur Système,,Cursore di sistema,システム,시스템 커서,Systeemcursor,Kursor systemu,Cursor do sistema,,,СиÑтемный курÑор,СиÑтемÑка Ñтрелица +Default,OPTVAL_DEFAULT,,,,Výchozí,Standard,,DefaÅ­lte,Por defecto,,Oletus,Défaut,,,デフォルト,기본 설정,Standaard,DomyÅ›lne,Padrão,,,По умолчанию,Подраз. +Configure Controller,JOYMNU_TITLE,,,,Konfigurovat ovladaÄ,Controller konfigurieren,,Agordi Ludregilon,Configurar Mando,,Peliohjainasetukset,Configurer Mannette,Kontroller testreszabása,Configura il controller,コントローラー構æˆ:,컨트롤러 구성,Controller configureren,Konfiguruj Kontroler,Configurar Controle,Configurar Comando,,ÐаÑтроить контроллер,Конфигурација контролера +Controller Options,JOYMNU_OPTIONS,,,,Nastavení ovladaÄe,Controlleroptionen,,Ludregilagordoj,Opciones del mando,,Peliohjainasetukset,Options Mannette,Kontroller beállításai,Opzioni del controller,コントローラー設定,컨트롤러 설정,Controller opties,Opcje Kontrolera,Opções de Controle,Opções do Comando,,ÐаÑтройки контроллера,Подешавања контролера +Block controller input in menu,JOYMNU_NOMENU,,,,Zakázat ovladaÄ v nabídkách,Blockiere Controllereingabe im Menü,,Blokigi ludregilon enigon en menuo,Bloq. entrada de mando en menú,,Estä ohjainsyötteet valikoissa,Bloquer manette dans les menus,Kontroller ne működjön a menüben,Blocca l'input del controller nei menu,メニューã§ã¯ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ãƒ¼ã‚’無視,메뉴ì—ì„œ 컨트롤러 ë„기,Blokkeer de controller in het menu,Blokuj wejÅ›cie kontrolera w menu,Bloquear controle no menu,Bloquear comando no menu,,Отключить контроллер в меню,Блокирај улаз контролера у менију +Enable controller support,JOYMNU_ENABLE,,,,Povolit podporu pro ovladaÄe,Erlaube Controllerunterstützung,,Aktivigi ludregilsubtenon,Activar soporte de mandos,,Ota käyttöön peliohjaintuki,Activer support contrôleur,,Abilita il supporto del controller,コントローラーサãƒãƒ¼ãƒˆè¨±å¯,컨트롤러 ì§€ì› í—ˆìš©,Controllerondersteuning inschakelen,WÅ‚Ä…cz wsparcie kontrolera,Habilitar suporte de controles,,,Включить поддержку контроллера,Омогући подршку за контролере +Enable DirectInput controllers,JOYMNU_DINPUT,,,,Povolit ovladaÄe DirectInput,Erlaube DirectInput-Controller,,Aktivigi DirectInput ludregilojn,Usa controles DirectInput,,Ota käyttöön DirectInput-ohjaimet,Activer contrôleurs DirectInput,,Abilita i controlli DirectInput,ダイレクトインプットコントローラー許å¯,다ì´ë ‰íŠ¸ ì¸í’‹ 컨트롤러 허용,DirectInput-controllers inschakelen,WÅ‚Ä…cz kontrolery DirectInput,Habilitar controles DirectInput,,,Включить контроллеры DirectInput,Омогући директинпут контролере +Enable XInput controllers,JOYMNU_XINPUT,,,,Povolit ovladaÄe XInput,Erlaube XInput-Controller,,Aktivigi XInput ludregilojn,Usa controles XInput,,Ota käyttöön XInput-ohjaimet,Activer contrôleurs XInput,,Abilita i controlli XInput,Xinput コントローラー許å¯,Xì¸í’‹ 컨트롤러 허용,XInput-controllers inschakelen,WÅ‚Ä…cz kontrolery XInput,Habilitar controles XInput,,,Включить контроллеры XInput,Омогући ИкÑинпут контролере +Enable raw PlayStation 2 adapters,JOYMNU_PS2,,,,Povolit ovladaÄe PlayStation 2,Erlaube Playstation 2-Controller,,Aktivigi krudajn PlayStation 2 adaptilojn,Usa adaptadores de PlayStation 2,,Ota käyttöön raa'at PlayStation 2 -adapterit,Activer adaptateurs PS2 bruts,,Abilita gli adattatori raw PlayStation 2,PlayStation2 アダプター許å¯,PS2 ì–´ëŽí„° 허용,Raw PlayStation 2-adapters inschakelen,WÅ‚Ä…cz adaptery PlayStation 2,Habilitar adaptadores de PlayStation 2,,,ИÑпользовать адаптеры PlayStation 2 напрÑмую,Омогући Ñирове ПлејÑтејшн 2 адаптере +No controllers detected,JOYMNU_NOCON,,,,Nenalezeny žádné ovladaÄe,Keine Controller gefunden,,Neniu ludregilojn detektas,No hay mandos detectados,,Ei havaittuja ohjaimia,Aucun Contrôleur détecté.,,Nessun controller trovato,コントローラーãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“,ì¸ì‹ëœ 컨트롤러 ì—†ìŒ,Geen controllers gedetecteerd,Nie wykryto kontrolerów,Nenhum controle detectado,Nenhum comando foi detectado,,Контроллеры не обнаружены,Ðема детектованих контролера +Configure controllers:,JOYMNU_CONFIG,,,,Nastavit ovladaÄe:,Controller konfigurieren,,Agordi ludregilojn:,Configurar controles:,,Mukauta ohjaimia:,Configurer contrôleurs:,,Configura i controller:,コントローラー構æˆ:,컨트롤러 설정:,Configureer controllers:,Konfiguruj kontrolery:,Configurar controles:,Configurar comandos,,ÐаÑтроить контроллер:,Подешавања контролере: +Controller support must be,JOYMNU_DISABLED1,,,,Podpora ovladaÄů musí být,Controllerunterstütung muss aktiviert sein,,Ludregilsubteno devas esti,El soporte de mandos debe estar,,Ohjaintuen täytyy olla otettu,Le Support de contrôleur doit être activé,,Il supporto ai controller deve essere,コントローラーサãƒãƒ¼ãƒˆã¯,ê°ì§€í•˜ë ¤ë©´ 컨트롤러 지ì›ì„,Controller ondersteuning moet ingeschakeld zijn,Wsparcie kontrolera musi być,Suporte à controles deve ser,Suporte a comandos devem ser,,Включите поддержку контроллера,Омогућите подржавање контролера +enabled to detect any,JOYMNU_DISABLED2,Supposed to be empty in Russian and Serbian.,,,zapnuta pro jejich detekování,um welche zu finden,,Åaltita detekti ajn,activado para detectar alguno,,käyttöön ohjainten havaitsemiseksi,avant de pouvoir en détecter un.,,abilitato a trovare ogni,検出ã—ã¾ã—ãŸ,활성화 해야합니다.,om eventuele regelaars te detecteren.,WÅ‚Ä…czony by wykryć jakikolwiek,habilitado para poder detectar algum,,, \n, \n +Invalid controller specified for menu,JOYMNU_INVALID,,,,Vybrán nesprávný ovladaÄ pro nabídky,Ungültiger Controller für Menü ausgewählt,,Malprava ludregilo specifigis por menuo,Mando inválido especificado para el menú,,Epäkelpo ohjain määritetty valikolle,Contrôleur invalide spécifé dans le menu.,,Controller invalido specificato per il menu,メニューã§ã¯ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ãƒ¼ã‚’使用ã—ãªã„,ë©”ë‰´ì— íŠ¹ì •ëœ ì»¨íŠ¸ë¡¤ëŸ¬ê°€ 아닙니다.,Ongeldige regelaar gespecificeerd voor het menu,NiewÅ‚aÅ›ciwy kontroler okreÅ›lony dla menu,Controle inválido especificado para o menu,Comando inválido,,ÐедопуÑтимый контроллер выбран Ð´Ð»Ñ Ð¼ÐµÐ½ÑŽ,Ðевалидан контролер Ñпецифиран за мени +Overall sensitivity,JOYMNU_OVRSENS,,,,Celková citlivost,Allgemeine Empfindlichkeit,,Tutsentemeco,Sensibilidad general,,Yleisherkkyys,Sensibilité générale,,Sensibilità generale,全体的ãªæ„Ÿåº¦,ì „ì²´ 민ê°ë„,Algemene gevoeligheid,Ogólna CzuÅ‚ość,Sensibilidade geral,,,ÐžÐ±Ñ‰Ð°Ñ Ñ‡ÑƒÐ²ÑтвительноÑÑ‚ÑŒ,Уупна ÑензитивноÑÑ‚ +Axis Configuration,JOYMNU_AXIS,,,,Nastavení os,Achsenkonfiguration,,Akso-agordoj,Configuración del eje,,Akseleiden säätäminen,Configuration des axes,,Configurazione assi,軸構æˆ,축 구성,Asconfiguratie,Konfiguruj OÅ›,Configuração de Eixo,,,ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð¾Ñей,Конфигурација оÑе +Invert,JOYMNU_INVERT,,,,Obrátit,Invertieren,,Inversigi,Invertir,,Käännä,Inverser,,Inverti,å転,순서 바꿈,Omkeren,Odwróć,Inverter,,,Инвертировать,Инвертовано +Dead zone,JOYMNU_DEADZONE,,,,Mrtvá zóna,Totzone,,Mortzono,Zona muerta,,Kuollut alue,Zone neutre,,Zona cieca,デッドゾーン,불ê°ëŒ€,Dode zone,Martwa strefa,Zona morta,,,ÐœÑ‘Ñ€Ñ‚Ð²Ð°Ñ Ð·Ð¾Ð½Ð°,Мртва зона +No configurable axes,JOYMNU_NOAXES,,,,Žádné nastavitelné osy,Keine konfigurierbaren Achsen,,Neniu agordeblaj aksoj,No hay ejes configurables,,Ei säädettäviä akseleita,Aucun axe à configurer,,Nessun asse configurabile,軸構æˆã‚’無効,설정할 방향키가 없습니다.,Geen configureerbare assen,Brak osi do skonfigurowania,Sem eixos configuráveis,,,Ðет наÑтраиваемых оÑей,Ðема конфигурационих оÑа +None,OPTVAL_NONE,,,,Žádný,Kein,,Neniu,Ninguno,,Ei mitään,Aucun,,Nessuno,ç„¡ã—,ì—†ìŒ,Geen,Å»aden,Nenhum,,,Откл.,Ðишта +Turning,OPTVAL_TURNING,,,,OtáÄení,Umdrehen,,Turnanta,Girar,,Kääntyminen,Tourner,,Rotazione,旋回,회전,Draaien,Obracanie siÄ™,Girar,,,Поворот,Скретање +Looking Up/Down,OPTVAL_LOOKINGUPDOWN,,,,Dívání se nahoru/dolů,Hoch/runterblicken,,Rigardanta Supre/Malsupre,Mirar hacia Arriba/Abajo,,Ylös/Alas katsominen,Vue haut/bas,,Sguardo Sopra/Sotto,視点上下,위/아래로 보기,Omhoog/omlaag zoeken,Patrzenie w górÄ™/w dół,Olhar para cima/baixo,,,ВзглÑд вверх/вниз,Гледање горе/доле +Moving Forward,OPTVAL_MOVINGFORWARD,,,,Pohyb vpÅ™ed,Vorwärtsbewegung,,Movanta Rekte,Avanzar,,Eteenpäin liikkuminen,Avancer,,Movimento in avanti,å‰é€²,앞으로 전진,Voorwaarts bewegen,Poruszanie siÄ™ do przodu,Mover para a frente,,,Движение вперёд,Кретање напред +Strafing,OPTVAL_STRAFING,,,,Pohyb do stran,Seitwärtsbewegung,,Flankmovanta,Desplazarse,,Sivuttaisastunta,Pas de côté,,Movimento laterale,横移動,양옆으로 ì´ë™,Strafelen,Uniki,Deslocamento lateral,,,Движение боком,Кретање у Ñтрану +Moving Up/Down,OPTVAL_MOVINGUPDOWN,,,,Pohyb nahoru/dolů,Auf/abwärtsbewegung,,Movanta Supre/Malsupre,Moverse hacia Arriba/Abajo,,Ylös/Alas liikkuminen,Mouvement haut/bas,,Movimento Sopra/Sotto,å‰é€²å¾Œé€€,위/아래로 ì´ë™,Naar boven/beneden bewegen,Poruszanie siÄ™ w górÄ™/w dół,Deslocar para cima/baixo,,,Движение вверх/вниз,Кретање горе/доле +Inverted,OPTVAL_INVERTED,,,,Inverzní,Invertiert,,Inversigita,Invertido,,Käännetty,Inversé,,Invertito,å転ã™ã‚‹,반전,Omgekeerd,Odwrócony,Invertido,,,Инвертировано,Обрнуто +Not Inverted,OPTVAL_NOTINVERTED,,,,Nikoliv inverzní,nicht invertiert,,Ne Inversigita,No invertido,,Ei käännetty,Non Inversé,,Non invertito,å転ã—ãªã„,반전ë˜ì§€ ì•ŠìŒ,Niet omgekeerd,Nieodwrócony,Não Invertido,,,ПрÑмо,Ðе обрнуто +,PLayer Menu,,,,,,,,,,,,,,,,,,,,,, +Player Setup,MNU_PLAYERSETUP,,,,Nastavení hráÄe,Spielereinstellungen,,Ludanto Agordaĵo,Config. del jugador,,Pelaaja-asetukset,Options Joueur,Játékos testreszabása,Settaggio giocatore,プレイヤーã®ç‰¹å¾´,플레ì´ì–´ 설정,Speler instellen,Ustawienia Gracza,Definições de Jogador,,,ÐаÑтройки игрока,Подешавања играча +Blue,TXT_COLOR_BLUE,,,,Modrá,Blau,,Blua,Azul,,Sininen,Bleu,Kék,Blu,é’,청색,Blauw,Niebieski,Azul,,,Синий,Плава +Red,TXT_COLOR_RED,,,,ÄŒervená,Rot,,RuÄa,Rojo,,Punainen,Rouge,Vörös,Rosso,赤,ì ìƒ‰,Rood,Czerwony,Vermelho,,,КраÑный,Црвена +Green,TXT_COLOR_GREEN,,,,Zelená,Grün,,Verda,Verde,,Vihreä,Vert,Zöld,Verde,ç·‘,녹색,Groen,Zielony,Verde,,,Зелёный,Зелена +Gray,TXT_COLOR_GRAY,,,Grey,Å edá,Grau,,Griza,Gris,,Harmaa,Gris,Szürke,Grigio,ç°,회색,Grijs,Szary,Cinza,,,Серый,Сива +Dark gray,TXT_COLOR_DARKGRAY,,,"Dark grey +",TmavÄ› Å¡edá,Dunkelgrau,,Grizeta,gris oscuro,,Tummanharmaa,Gris sombre,Sötétszürke,Grigio scuro,鉛,치색,Donkergrijs,Ciemnoszary,Cinza escuro,,,Тёмно-Ñерый,Тамно Ñива +Dark Green,TXT_COLOR_DARKGREEN,,,,TmavÄ› zelená,Dunkelgrün,,Malhelverda,Verde oscuro,,Tummanvihreä,Vert sombre,Sötétzöld,Verde scuro,æ·±,í‘녹색,Donkergroen,Ciemnozielony,Verde escuro,,,Тёмно-зелёный,Тамна зелена +Brown,TXT_COLOR_BROWN,,,,HnÄ›dá,Braun,,Bruna,Marrón,,Ruskea,Brun,Barna,Marrone,茶,갈색,Bruin,BrÄ…zowy,Marrom,,,Коричневый,Браон +Dark Blue,TXT_COLOR_DARKBLUE,,,,TmavÄ› modrá,Dunkelblau,,Malhelblua,Azul oscuro,,Tummansininen,Bleu sombre,Sötétkék,Blu scuro,,,Donkerblauw,,Azul escuro,,,Тёмно-Синий,Тамна Плава +Light Red,TXT_COLOR_LIGHTRED,,,,SvÄ›tle Äervená,Hellrot,,RuÄeta,Rojo claro,,Vaaleanpunainen,Rouge clair,,Rosso chiaro,丹,ì˜…ì€ ì ìƒ‰,Licht Rood,Jasnoczerwony,Vermelho claro,,,Светло-краÑный,Светло црвена +Yellow,TXT_COLOR_YELLOW,,,,Žlutá,Gelb,,Flava,Amarillo,,Keltainen,Jaune,Sárga,Giallo,黄,노란색,Geel,Żółty,Amarelo,,,Жёлтый,Жута +Purple,TXT_COLOR_PURPLE,,,,Fialová,Violett,,Purpura,Morado,,Purppura,Violet,Lila,Viola,ç´«,ë³´ë¼ìƒ‰,Paars,Fioletowy,Roxo,,,Фиолетовый,ЉубичаÑта +Olive,TXT_COLOR_DULLGREEN,,,,BledÄ› zelená,Blassgrün,,Gris-Verda,Verde pálido,,Haaleanvihreä,Vert pâle,,Verde pallido,è‹”,암녹색,Saaie groen,Matowa ZieleÅ„,Verde pálido,,,Мутно-зелёный,Тупа зелена +Auto,OPTVAL_AUTO,,,,,,,AÅ­tomata,Automático,,Automaattinen,,,Automatico,自動,ìžë™,,Automatycznie,Automático,,,Ðвто,ÐутоматÑки +Name,PLYRMNU_NAME,,,,Jméno,,,Nomo,Nombre,,Nimi,Nom,Név,Nome,åå‰,ì´ë¦„,Naam,ImiÄ™,Nome,,,ИмÑ,Ðадимак +Team,PLYRMNU_TEAM,,,,Tým,,,Teamo,Equipo,,Joukkue,Equipe,Csapat,Squadra,ãƒãƒ¼ãƒ ,팀,Team,Drużyna,Equipe,Equipa,,Команда,Тим +Color,PLYRMNU_PLAYERCOLOR,,,Colour,Barva,Farbe,,Koloro,,,Väri,Couleur,Szín,Colore,色,색ìƒ,Kleur,Kolor,Cor,,,Цвет,Боја +Multiplayer taunts,PLRMNU_TAUNTS,,,,,Mehrspieler-Spott,,,,,,,,,,,,,,,,, +Gender,PLYRMNU_PLAYERGENDER,,,,Pohlaví,Geschlecht,,Genro,Género,,Sukupuoli,Genre,Nem,Sesso,性別,성별,Geslacht,PÅ‚eć,Gênero,,,Пол,Пол +Male,OPTVAL_MALE,,,,Muž,Männlich,,Vira (Li),Masculino,,Miespuolinen,Masculin,,Maschio,ç”·,남성,Man,Mężczyzna,Masculino,,,МужÑкой,Мушко +Female,OPTVAL_FEMALE,,,,Žena,Weiblich,,Ina (Åœi),Femenino,,Naispuolinen,Féminin,,Femmina,女,여성,Vrouw,Kobieta,Feminino,,,ЖенÑкий,ЖенÑко +Neutral,OPTVAL_NEUTRAL,,,,Neutrální,Neutral,,NeÅ­trala (Ri),Neutro,,Sukupuoleton,Neutre,,Neutrale,中間,중성,Neutraal,Neutralne,Neutro,,,Ðейтральный,Ðеутрално +Object,OPTVAL_OTHER,,,,Objekt,Objekt,,Objekto (Äœi),Objeto,,Olio,Objet,,Oggetto,物体,기타,Doel,Obiekt,Objeto,,,Предмет,Предмет +,Multiplayer,,,,,,,,,,,,,,,,,,,,,, +Game Options,NETMNU_OPTIONS,,,,,Spieleinstellungen,,,,,,,,,,,,,,,,, +Launch Game,NETMNU_LAUNCH,,,,,Spiel starten,,,,,,,,,,,,,,,,, +Game Type,NETMNU_GAMETYPE,,,,,,,,,,,,,,,,,,,,,, +Deathmatch (Spawn),NETMNU_GAMETYPE1,,,,,,,,,,,,,,,,,,,,,, +DukeMatch (Spawn),NETMNU_GAMETYPE1,Duke,,,,,,,,,,,,,,,,,,,,, +GI Match (Spawn),NETMNU_GAMETYPE1,Nam,,,,,,,,,,,,,,,,,,,,, +GruntMatch (Spawn),NETMNU_GAMETYPE1,WW2GI,,,,,,,,,,,,,,,,,,,,, +Cooperative Play,NETMNU_GAMETYPE2,,,,,,,,,,,,,,,,,,,,,, +Deathmatch (No Spawn),NETMNU_GAMETYPE3,,,,,,,,,,,,,,,,,,,,,, +DukeMatch (No Spawn),NETMNU_GAMETYPE3,Duke,,,,,,,,,,,,,,,,,,,,, +GI Match (No Spawn),NETMNU_GAMETYPE3,Nam,,,,,,,,,,,,,,,,,,,,, +GruntMatch (No Spawn),NETMNU_GAMETYPE3,WW2GI,,,,,,,,,,,,,,,,,,,,, +Team DM (Spawn),NETMNU_GAMETYPE4,,,,,,,,,,,,,,,,,,,,,, +Team DM (No Spawn),NETMNU_GAMETYPE5,,,,,,,,,,,,,,,,,,,,,, +Episode,NETMNU_EPISODE,,,,,,,,,,,,,,,,,,,,,, +Level,NETMNU_LEVEL,,,,,,,,,,,,,,,,,,,,,, +Monsters,NETMNU_MONSTERS,,,,,,,,,,,,,,,,,,,,,, +Markers,NETMNU_MARKERS,,,,,,,,,,,,,,,,,,,,,, +Map Exits,NETMNU_MAPEXITS,,,,,,,,,,,,,,,,,,,,,, +Friendly Fire,NETMNU_FFIRE,,,,,,,,,,,,,,,,,,,,,, +Accept,NETMNU_ACCEPT,,,,,,,,,,,,,,,,,,,,,, +Server,NETMNU_SERVER,,,,,,,,,,,,,,,,,,,,,, +Port,NETMNU_PORT,Network port!,,,,,,,,,,,,,,,,,,,,, +Connect,NETMNU_CONNECT,,,,,,,,,,,,,,,,,,,,,, +,Gameplay options,,,,,,,,,,,,,,,,,,,,,, +Gameplay Options,GMPLYMNU_TITLE,,,,Nastavení herních mechanik,Gameplay-Optionen,,Ludadagordoj,Opciones de jugabilidad,,Pelattavuusasetukset,Options Gameplay,,Opzioni gameplay,ゲームプレイ オプション,ê²Œìž„í”Œë ˆì´ ì„¤ì •,Gameplay-opties,Opcje Rozgrywki,Opções de Jogabilidade,,,ÐаÑтройки геймплеÑ,Подешавања гејмплеја +Always,OPTVAL_ALWAYS,,,,Vždy,Immer,,Ĉiam,Siempre,,Aina,Toujours,,Sempre,常ã«,언제나,Altijd,Zawsze,Sempre,,,Ð’Ñегда,Увек +Never,OPTVAL_NEVER,,,,Nikdy,Nie,,Neniam,Nunca,,Ei koskaan,Jamais,,Mai,ã—ãªã„,ì—†ìŒ,Nooit,Nigdy,Nunca,,,Ðикогда,Ðикад +Hitscan only,OPTVAL_HITSCAN,,,,,Nur Hitscan,,,,,,,,,,,,,,,,, +Autoaim,PLYRMNU_AUTOAIM,,,,Automatické míření,Automatisch zielen,,AÅ­tomate-celi,Autoapuntar,,Automaattitähtäys,Auto-visée,Auto célzás,Mira automatica,自動照準,ìžë™ 조준,Autoaim,Automatyczne Celowanie,Mira Automática,,,Ðвтоприцеливание,ÐутоматÑко циљање +Always Run,PLYRMNU_ALWAYSRUN,,,,Vždy běžet,Immer Rennen,,Ĉiam Kuri,Siempre correr,,Jatkuva juoksu,Toujours courir,Mindig fusson,Corri sempre,常ã«é§†ã‘足,달리기 토글,Altijd lopen,Zawsze Biegaj,Sempre Correr,Correr Sempre,,ПоÑтоÑнный бег,Увек трчи +Run Mode,PLRMNU_RUNMODE,,,,,Rennmodus,,,,,,,,,,,,,,,,, +Allow Toggle,PLRMNU_TOGGLE,,,,,Umschalten erlauben,,,,,,,,,,,,,,,,, +Override Toggle,PLRMNU_OVERRIDE,,,,,Umschalten blockieren,,,,,,,,,,,,,,,,, +If New,PLRMNU_IFNEW,,,,,Wenn neu,,,,,,,,,,,,,,,,, +Equip Weapon Pickups,PLRMNU_EQUIP,,,,,Waffen sofort aktivieren,,,,,,,,,,,,,,,,, +Parental Lock,PLRMNU_PLOCK,,,,,Kindersicherung,,,,,,,,,,,,,,,,, +Only preferred,PLRMNU_PREFERRED,,,,,Nur bevorzugte,,,,,,,,,,,,,,,,, +,Display/HUD,,,,,,,,,,,,,,,,,,,,,, +Display Options,DSPLYMNU_TITLE,,,,Nastavení grafiky,Anzeigeoptionen,,Ekranagordoj,Opciones de visualización,,Näyttöasetukset,Options Affichage,Megjelenítés beállítások,Opzioni display,ディスプレイ オプション,ë””ìŠ¤í”Œë ˆì´ ì„¤ì •,Weergaveopties,Opcje WyÅ›wietlania,Opções de Vídeo,,,ÐаÑтройки Ñкрана,Подешавања приказа +Screen size,DSPLYMNU_SCREENSIZE,,,,Velikost obrazovky,Bildschirmgröße,,Ekrano-grandeco,Tamaño de pantalla,,Näytön koko,Taille de l'écran,KépernyÅ‘ mérete,Dimensione della schermata,ç”»é¢ã‚µã‚¤ã‚º,화면 í¬ê¸°,Schermgrootte,Rozmiar Ekranu,Tamanho de tela,Tamanho do ecrã,,Размер Ñкрана,Величина екрана +Vertical Sync,DSPLYMNU_VSYNC,,,,Vertikální synchronizace,Vertikale Synchronisation,,Vertikala-sinkronigo,Sincr. vertical,,Pystytahdistys,Synchronisation Verticale,FüggÅ‘leges szinkronizálás,Sync verticale,åž‚ç›´åŒæœŸ,ìˆ˜ì§ ë™ê¸°í™”,Verticale Sync,Synchronizacja Pionowa,Sincronização Vertical,,,Ð’ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð°Ñ ÑинхронизациÑ,Вертикална Ñинхорнизација +Models,DSPLYMNU_MODELS,,,,Modely,Modelle,,Modeloj,Modelos,,Mallit,Modèles,3D modellek,Modelli,モデル,모ë¸,Modellen,Modele,Modelos,,,Модели,Модели +Voxels,DSPLYMNU_VOXELS,,,,,Voxel,,,,,,,,,,,,,,,,, +Scale crosshair,DSPLYMNU_CROSSHAIRSCALE,,,,Velikost zaměřovaÄe,Fadenkreuz skalieren,,Skali translinion,Escalar retícula,,Skaalaa tähtäintä,Mise à l'échelle du viseur,,Scala del mirino,照準サイズ,ì¡°ì¤€ì  í¬ê¸°,Dradenkruis schalen,Skala celownika,Escala da mira,,,МаÑштабирование прицела,Размера нишана +Brightness,DSPLYMNU_BRIGHTNESS,,,,Jas,Helligkeit,,Brileco,Brillo,,Kirkkaus,Luminosité,FényerÅ‘,Luminosità,明るã•,ë°ê¸°,Helderheid,Jasność,Brilho,,,ЯркоÑÑ‚ÑŒ,ОÑветљење +Gamma correction,DSPLYMNU_GAMMA,,,,Korekce gama,Gammakorrektur,,Gamaa korektado,Corrección gamma,,Gammakorjaus,Correction Gamma,,Correzione gamma,ガンマ値,ê°ë§ˆ ì¡°ì •,Gamma correctie,Korekta gammy,Correção gama,,,Гамма-коррекциÑ,Корекција ÑветлоÑти +Contrast,DSPLYMNU_CONTRAST,,,,Kontrast,Kontrast,,Kontrasto,Contraste,,Sävykkyys,Contraste,,Contrasto,コントラスト,대비,,Kontrast,Contraste,,,КонтраÑÑ‚,КонтраÑÑ‚ +Saturation,DSPLYMNU_SATURATION,,,,Sytost,Sättigung,,Satureco,Saturación,,Värikylläisyys,,,Saturazione,サãƒãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³,채ë„,Verzadiging,Nasycenie,Saturação,,,ÐаÑыщенноÑÑ‚ÑŒ,Сатурација +Status Bar Scale,DSPLYMNU_SBSCALE,,,,,Statusleistengröße,,,,,,,,,,,,,,,,, +Level statistics,DSPLYMNU_LEVELSTATS,,,,,Levelstatistik,,,,,,,,,,,,,,,,, +Text Scale,DSPLYMNU_TEXTSCALE,,,,,Textgröße,,,,,,,,,,,,,,,,, +Messages,DSPLYMNU_MESSAGES,,,,Zprávy,Nachrichten,,MesaÄoj,Mensajes,,Viestit,Messages,,Messaggi,メッセージ類,메시지,Berichten,WiadomoÅ›ci,Mensagens,,,СообщениÑ,Поруке +Generic,DSPLYMNU_GENERIC,,,,,Generisch,,,,,,,,,,,,,,,,, +Show Map Name,DSPLYMNU_SHOWMAPNAME,,,,,"Levelnamen anzeigen +",,,,,,,,,,,,,,,,, +FOV,DSPLYMNU_FOV,,,,,Gesichtsfeld,,,,,,,,,,,,,,,,, +Crosshair,DSPLYMNU_CROSSHAIR,,,,Křížek,Fadenkreuz,,Reteto,Retícula,,Tähtäin,Viseur,,Mirino,クロスヘア,조준ì ,Draadkruis,Celownik,Mira,,,Прицел,Ðишан +HUD Options,OPTMNU_HUD,,,,Nastavení HUD,HUD Einstellungen,,Agordoj de HUD,Opciones del HUD,,Tilanäytön asetukset,Options de l'ATH,HUD beállítások,Opzioni HUD,HUD オプション,HUD 설정,HUD opties,Opcje Paska HUD,Opções de HUD,,,HUD,HUD +Polymost Options,OPTMNU_POLYMOST,,,,,Polymost Einstellungen,,,,,,,,,,,,,,,,, +Texture Filter mode,GLTEXMNU_TEXFILTER,,,,Režim filtrování textur,Texturfiltermodus,,ReÄimo por Teksturfiltrado,Modo de filtro de texturas,,Pintakuviointien suodatustapa,Mode de Filtrage Texture,,Modalità filtro texture,テクスãƒãƒ£ãƒ¼ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ モード,í…ìŠ¤ì³ í•„í„° 모드,Textuur Filter mode,Tryb Filtrowania Tekstur,Modo de filtragem de textura,,,Ð¤Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ñ‚ÐµÐºÑтур,ТекÑтурни филтер мод +Anisotropic filter,GLTEXMNU_ANISOTROPIC,,,,Anisotropické filtrování,Anisotropische Filterung,,Anizotropa Filtro,Filtro anisotrópico,,Anisotrooppinen suodatus,Filtre Anisotropique,,Filtro anisotropico,異方性フィルター,ì´ë°©ì„± í•„í„°,Anisotroop filter,Filtr anizotropowy,Filtragem anisotrópica,,,ÐÐ½Ð¸Ð·Ð¾Ñ‚Ñ€Ð¾Ð¿Ð½Ð°Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ,Ðнизотропни фолтер +None (nearest mipmap),OPTVAL_NONENEARESTMIPMAP,,,,Žádné (nejbližší mipmapa),Aus (nächste Mipmap),,Nenio (plej proksima mipmapo),Ninguno (mipmap cercano),,Ei mitään (lähin mipkartta),Aucun (mipmap proche voisin),,Nessuno (mipmap più vicina),ãªã—(最寄りミップマップ),ì—†ìŒ (ë°‰ë©¥ì— ê°€ê¹Œì›€),Geen (dichtstbijzijnde mipmap),Brak (najbliższa mipmapa),Nenhum (mipmap vizinho mais próximo),,,Ðет (ближайший мипмап),Ðишта (најближи мипмап) +None (linear mipmap),OPTVAL_NONELINEARMIPMAP,,,,Žádné (lineární mipmapa),Aus (lineare Mipmap),,Nenio (linia mipmapo),Ninguno (mipmap lineal),,Ei mitään (lin. mipkartta),Aucun (mipmap linéaire),,Nessuno (mipmap lineare),ãªã—(リニアミップマップ),ì—†ìŒ (선형 밉맵),Geen (lineaire mipmap),Brak (liniowa mipmapa),Nenhum (mipmap linear),,,Ðет (линейный мипмап),Ðишта (линеаран мипмап) +None (trilinear),OPTVAL_NONETRILINEAR,,,,Žádné (trilineární),Aus (trilinear),,Nenio (trilinia),Ninguno (trilineal),,Ei mitään (trilineaarinen),Aucun (mipmap trilinéaire),,Nessuno (mipmap trilineare),ãªã—(トライリニア),ì—†ìŒ (삼선형),Geen (trilineair),Brak (trzyliniowe),Nenhum (trilinear),,,Ðет (трилинейнаÑ),Ðишта (трилинеарно) +Bilinear,OPTVAL_BILINEAR,,,,Bilineární,,,Dulinia,Bilineal,,Bilineaarinen,Bilinéaire,,Bilineare,ãƒã‚¤ãƒªãƒ‹ã‚¢,ìŒì„ í˜•,Bilineair,Dwuliniowe,,,,БилинейнаÑ,Билинеарно +Trilinear,OPTVAL_TRILINEAR,,,,Trilineární,,,Trilinia,Trilineal,,Trilineaarinen,Trilinéaire,,Trilineare,トライリニア,삼선형,Trilineair,Trzyliniowe,,,,ТрилинейнаÑ,Трилинеарно +2x,OPTVAL_2X,,,,,,,2-oble,,,,,,,,,,,,,,, +4x,OPTVAL_4X,,,,,,,4-oble,,,,,,,,,,,,,,, +8x,OPTVAL_8X,,,,,,,8-oble,,,,,,,,,,,,,,, +16x,OPTVAL_16X,,,,,,,16-oble,,,,,,,,,,,,,,, +32x,OPTVAL_32X,,,,,,,32-oble,,,,,,,,,,,,,,, +,Polymost,,,,,,,,,,,,,,,,,,,,,, +True Color Textures,POLYMOST_TC,,,True Colour Textures,,True Color Texturen,,,,,,,,,,,,,,,,, +Pre-load map textures,POLYMOST_CACHE,,,,,Texturen cachen,,,,,,,,,,,,,,,,, +Detail Textures,POLYMOST_DETAIL,,,,,Detailtexturen,,,,,,,,,,,,,,,,, +Glow Textures,"POLYMOST_GLOW +",,,,,Leucht-Texturen,,,,,,,,,,,,,,,,, +3D-Models,POLYMOST_MODELS,,,,,3D Modelle,,,,,,,,,,,,,,,,, +"Polymost Options +",POLYMOST_OPTIONS,,,,,Polymost-Optionen,,,,,,,,,,,,,,,,, +Palette Emulation,POLYMOST_PALETTEEMU,,,,,Palettenemulation,,,,,,,,,,,,,,,,, +Palette Interpolation,POLYMOST_PALINTER,,,,,Paletteninterpolation,,,,,,,,,,,,,,,,, +,Sound,,,,,,,,,,,,,,,,,,,,,, +4000 Hz,OPTVAL_4000HZ,,,,,,,,,,,,,,,,,,,,,4000 Гц, +8000 Hz,OPTVAL_8000HZ,,,,,,,,,,,,,,,,,,,,,8000 Гц, +11025 Hz,OPTVAL_11025HZ,,,,,,,,,,,,,,,,,,,,,11025 Гц, +22050 Hz,OPTVAL_22050HZ,,,,,,,,,,,,,,,,,,,,,22050 Гц, +32000 Hz,OPTVAL_32000HZ,,,,,,,,,,,,,,,,,,,,,32000 Гц, +44100 Hz,OPTVAL_44100HZ,,,,,,,,,,,,,,,,,,,,,44100 Гц, +48000 Hz,OPTVAL_48000HZ,,,,,,,,,,,,,,,,,,,,,48000 Гц, +64 samples,OPTVAL_64SAMPLES,,,,64 vzorků,64 Samples,,64 specimenoj,64 Muestras,,64 näytettä,,,,,64 샘플,,64 sample,64 amostras,,,64 Ñемпла,64 узорка +128 samples,OPTVAL_128SAMPLES,,,,128 vzorků,128 Samples,,128 specimenoj,128 Muestras,,128 näytettä,,,,,128 샘플,,128 sampli,128 amostras,,,128 Ñемплов,128 узорка +256 samples,OPTVAL_256SAMPLES,,,,256 vzorků,256 Samples,,256 specimenoj,256 Muestras,,256 näytettä,,,,,256 샘플,,256 sampli,256 amostras,,,256 Ñемплов,256 узорка +512 samples,OPTVAL_512SAMPLES,,,,512 vzorků,512 Samples,,512 specimenoj,512 Muestras,,512 näytettä,,,,,512 샘플,,512 sampli,512 amostras,,,512 Ñемплов,512 узорка +1024 samples,OPTVAL_1024SAMPLES,,,,1024 vzorků,1024 Samples,,1024 specimenoj,1024 Muestras,,1024 näytettä,,,,,1024 샘플,,1024 sampli,1024 amostras,,,1024 Ñемпла,1024 узорка +2048 samples,OPTVAL_2048SAMPLES,,,,2048 vzorků,2048 Samples,,2048 specimenoj,2048 Muestras,,2048 näytettä,,,,,2048 샘플,,2048 sampli,2048 amostras,,,2048 Ñемплов,2048 узорка +4096 samples,OPTVAL_4096SAMPLES,,,,4096 vzorků,4096 Samples,,4096 specimenoj,4096 Muestras,,4096 näytettä,,,,,4096 샘플,,4096 sampli,4096 amostras,,,4096 Ñемплов,4096 узорка +Auto,OPTSTR_AUTO,,,,,,,AÅ­tomata,Automático,,Automaattinen,,,Automatico,自動,오토,,Automatycznie,Automático,,,Ðвто,ÐутоматÑки +Mono,OPTSTR_MONO,,,,,,,1 LaÅ­tparolilo,,,,,,,モノラル,모노,,,,,,Моно,Монотоно +Stereo,OPTSTR_STEREO,,,,,,,2 LaÅ­tparoliloj,Estereo,,,Stéréo,,,ステレオ,스테레오,,,Estéreo,,,Стерео,Стереотоно +Dolby Pro Logic Decoder,OPTSTR_PROLOGIC,,,,,,,Malkodilo de Dolby Pro Logic ,,,,,,,ドルビー プロロジック デコーダー,ëŒë¹„ 프로 ë¡œì§ ë””ì½”ë”,,,,,,Декодер Dolby Pro Logic, +Quad,OPTSTR_QUAD,,,,,,,4 LaÅ­tparolilol,Cuádruple,,Dolby Pro Logic -dekooderi,,,,クァッド,쿼드,,Cztery kanaÅ‚y,,,,Четырёхканальный,Четвородупло +5 speakers,OPTSTR_SURROUND,,,,5 reproduktorů,5 Lautsprecher,,5 LaÅ­tparoliloj,5 altavoces,5 Bocinas,5 kaiutinta,5 enceintes,,,5 スピーカー,5 스피커,5 luidsprekers,GÅ‚oÅ›niki 5,5 alto falantes,,,5 динамиков,5 Ñпикер +5.1 speakers,OPTSTR_5POINT1,,,,Reproduktory 5.1,5.1 Lautsprecher,,5.1 LaÅ­tparoliloj,Altavoces 5.1,Bocinas 5.1,5.1 kaiutinta,Enceintes 5.1,,,5.1 スピーカー,5.1 스피커,5.1 luidsprekers,GÅ‚oÅ›niki 5.1,Auto falantes 5.1,,,Динамики 5.1,5.1 Ñпикер +7.1 speakers,OPTSTR_7POINT1,,,,Reproduktory 7.1,7.1 Lautsprecher,,7.1 Laůtparoliloj,Altavoces 7.1,Bocinas 7.1,7.1 kaiutinta,Enceintes 7.1,,,7.1 スピーカー,7.1스피커,7.1 luidsprekers,GÅ‚oÅ›niki 7.1,Auto falantes 7.1,,,Динамики 7.1,7.1 Ñпикер +OpenAL Options,OPENALMNU_TITLE,,,,Nastavení OpenAL,OpenAL Optionen,,OpenAL-agordoj,Opciones de OpenAL,,OpenAL-asetukset,Options OpenAL,,Opzioni OpenAL,OpenAL オプション,오픈ì—ì´ì—˜ 설정,OpenAL opties,Opcje OpenAL,Opções de OpenAL,,,ÐаÑтройки OpenAL,OpenAL подешавања +Playback device,OPENALMNU_PLAYBACKDEVICE,,,,PÅ™ehravací zařízení,Wiedergabegerät,,Ludado-aparato,Dispositivo de reproducción,,Äänitoistolaite,Sortie sonore,,Dispositivo di playback,プレイãƒãƒƒã‚¯ デãƒã‚¤ã‚¹,ìž¬ìƒ ìž¥ì¹˜,Afspeelapparaat,UrzÄ…dzenie odtwarzania,Dispositivo de reprodução,,,УÑтройÑтво воÑпроизведениÑ,Ðудио уређај +Enable EFX,OPENALMNU_ENABLEEFX,,,,Povolit EFX,EFX aktiv,,Aktivigi EFX,Permitir EFX,,Ota käyttöön EFX,Activer EFX,,Abilita EFX,EFXを有効化,EFX 켬,EFX inschakelen,Pozwól na EFX,Habilitar EFX,,,Включить EFX,Укључи EFX +Resampler,OPENALMNU_RESAMPLER,,,,,,,Respecimenilo,,,Näytteenottotaajuusmuunnin,,,,リサンプラー,재배열 기기,,Resampler,,,,РеÑÑмплер,РеÑемплер +Sound Options,SNDMNU_TITLE,,,,Nastavení zvuku,Soundeinstellungen,,Son-agordoj,Opciones de sonido,,Ääniasetukset,Options Sonores,Hangbeállítások,Opzioni del suono,サウンド オプション,ìŒí–¥ 설정,Geluidsopties,Opcje DźwiÄ™ku,Opções de Ãudio,,,ÐаÑтройки звука,Звучна подешавања +Sounds volume,SNDMNU_SFXVOLUME,,,,Hlasitost zvuků,Effektlautstärke,,Son-laÅ­tec-menuo,Volumen de sonido,,Äänitehosteiden voimakkuus,Volume des Sons,Effektek hangereje,Volume suoni,効果音音é‡,íš¨ê³¼ìŒ ìŒëŸ‰,Geluidsvolume,GÅ‚oÅ›ność DźwiÄ™ku,Volume de sons,,,ГромкоÑÑ‚ÑŒ звука,Јачина звука +Menu volume,SNDMNU_MENUVOLUME,,,,Hlasitost nabídek,Menülautstärke,,Menu-laÅ­teco,Volumen del menú,,Valikon äänenvoimakkuus,Volume du Menu,Menü hangereje,Volume menu,メニュー音é‡,메뉴 ìŒëŸ‰,Menu volume,GÅ‚oÅ›ność Menu,Volume do menu,,,ГромкоÑÑ‚ÑŒ меню,Јачина менија +Music volume,SNDMNU_MUSICVOLUME,,,,Hlasitost hudby,Musiklautstärke,,Muzik-laÅ­teco,Volumen de la Música,,Musiikin äänenvoimakkuus,Volume Musique,Zene hangereje,Volume musica,音楽音é‡,ë°°ê²½ìŒ ìŒëŸ‰,Muziekvolume,GÅ‚oÅ›ność Muzyki,Volume da música,,,ГромкоÑÑ‚ÑŒ музыки,Јачина музике +MIDI device,SNDMNU_MIDIDEVICE,,,,MIDI zařízení,MIDI-Gerät,,MIDI-aparato,Dispositivo MIDI,,MIDI-laite,Sortie MIDI,MIDI eszköz,Dispositivo MIDI,MIDIデãƒã‚¤ã‚¹,MIDI 장치,MIDI-apparaat,UrzÄ…dzenie MIDI,Dispositivo MIDI,,,MIDI проигрыватель,MIDI уређај +Sound in Background,SNDMNU_BACKGROUND,,,,Zvuk na pozadí,Sound im Hintergrund,,Sono en Fono,Sonido en segundo plano,,Ääni taustalla,Son activé en arrière plan,Háttérhangok,Suono di sottofondo,ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§ã®ã‚µã‚¦ãƒ³ãƒ‰,배경화면ì—ì„œë„ ì†Œë¦¬ 재ìƒ,Geluid in de achtergrond,DźwiÄ™k w Tle,Som de Fundo,,,Звуки в фоне,Звуци у позадини +Underwater reverb,SNDMNU_UNDERWATERREVERB,,,,OzvÄ›na pod vodou,Unterwasserhall,,Subakva resono,Reverb. bajo el agua,,Vedenalaiskaiku,Reverbération sous l'eau,Vízalatti viszhang,Reverb sott'acqua,水中å響音,수중 울림효과,Onderwater nagalm,PogÅ‚os pod wodÄ…,Reverberação debaixo d'água,Reverberação debaixo de água,,Эффект под водой,Подводни одјек +Randomize pitches,SNDMNU_RANDOMIZEPITCHES,,,,Náhodné výšky tónu,Zufällige Tonhöhe,,Malcertigi son-peĉojn,Tonos aleatorios,,Satunnaista äänenkorkeuksia,Tons sonores aléatoires,Hangmagasság véletlenszerű,Rendi casuale il tono,ランダマイズ ピッãƒ,ìŒë†’ì´ ë¬´ìž‘ìœ„í™”,Willekeurige plaatsen,Losuj tonacje,Aleatorizar tons,Tons aleatórios,,ИзменÑÑ‚ÑŒ выÑоту,Рандомизација тонова +Sound channels,SNDMNU_CHANNELS,,,,PoÄet zvukových kanálů,Soundkanäle,,Son-kanaloj,Canales de sonido,,Äänikanavat,Canaux sonores,Hangcsatorna,Numero canali del suono,サウンド ãƒãƒ£ãƒ³ãƒãƒ«,ìŒí–¥ 채ë„,Geluidskanalen,KanaÅ‚y dźwiÄ™kowe,Canais de som,,,КоличеÑтво каналов,Звучни канали +Sound backend,SNDMNU_BACKEND,,,,Zvukový systém,Soundsystem,,Son-servilo,Sistema de sonido,,Äänijärjestelmä,Traitement Son,,Backend suono,サウンド ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰,ìŒí–¥ ë§ë¯¸,Geluidsarme achterkant,System dźwiÄ™kowy,Sistema de som,,,Ð—Ð²ÑƒÐºÐ¾Ð²Ð°Ñ ÑиÑтема,Звучни бекенд +OpenAL options,SNDMNU_OPENAL,,,,Nastavení OpenAL,OpenAL Optionen,,OpenAL-agordoj,Opciones de OpenAL,,OpenAL-asetukset,Options OpenAL,OpenAL beállításai,Opzioni OpenAL,OpenAL オプション,오픈ì—ì´ì—˜ 설정,OpenAL opties,Opcje OpenAL,Opções de OpenAL,,,ÐаÑтройки OpenAL,OpenAL подешавања +Restart sound,SNDMNU_RESTART,,,,Restartovat zvuk,Sound neu starten,,Rekomenci sonon,Reiniciar sonido,,Käynnistä ääni uudelleen,Redémarrer moteur sonore,Hang újraindítása,Resetta il suono,サウンドå†èµ·å‹•,ìŒí–¥ 재시작,Herstart geluid,Zresetuj dźwiÄ™k,Reiniciar som,,,ПерезапуÑтить звук,Поново покрени звук +Advanced options,SNDMNU_ADVANCED,,,,PokroÄilá nastavení,Erweiterte Optionen,,Altnivelaj agordoj,Opciones avanzadas,,Edistyneet asetukset,Options avancées,Haladó beállítások,Opzioni avanzate,高度ãªã‚ªãƒ—ション,고급 설정,Geavanceerde opties,Zaawansowane Opcje,Opções avançadas,,,РаÑширенные наÑтройки,Ðапредна подешавања +Module replayer options,SNDMNU_MODREPLAYER,,,,Nastavení pÅ™ehrávaÄe modulů,Modul-Spieler-Optionen,,Agordoj por modulreludilo,Opciones reproductor de módulos,,Moduulisoitinasetukset,Options lecteur de module,,Opzioni Module replayer,モジュールリプレイヤー オプション,모듈 ìž¬ìƒ ì„¤ì •,Module replayer opties,Opcje ModuÅ‚u Odtwarzacza,Opções de reprodutor de módulos,,,Параметры воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð´ÑƒÐ»ÐµÐ¹,Подешавања модулног риплејера +Midi player options,SNDMNU_MIDIPLAYER,,,,Nastavení MIDI pÅ™ehrávaÄe,MIDI-Spieler-Optionen,,Agordoj por MIDI-ludilo,Opciones de reproductor MIDI,,MIDI-soitinasetukset,Option lecteur MIDI,,Opzioni Midi player,Midiå†ç”Ÿã®ã‚ªãƒ—ション,MIDI 플레ì´ì–´ 설정,Midi speler opties,Opcje Odtwarzacza Midi,Opções de reprodutor MIDI,,,ÐаÑтройки MIDI-проигрывателÑ,MIDI плејер подешавања +Sound in Menus,SNDMNU_MENUSOUND,,,,,Sound in Menüs,,,,,,,,,,,,,,,,, +Advanced Sound Options,ADVSNDMNU_TITLE,,,,PokroÄilá nastavení zvuku,Erweiterte Soundoptionen,,Altnivelaj Son-agordoj,Opciones avanzadas de sonido,,Edistyneet ääniasetukset,Options Sonores Avancées,,Opzioni avanzate dei suoni,高度ãªã‚µã‚¦ãƒ³ãƒ‰ã‚ªãƒ—ション,고급 ìŒí–¥ 설정,Geavanceerde geluidsopties,Zaawansowane Opcje DźwiÄ™ku,Opções de Ãudio Avançadas,,,РаÑширенные наÑтройки,Ðапредна подешавања звука +Sample rate,ADVSNDMNU_SAMPLERATE,,,,Vzorkovací frekvence,Samplerate,,Specimenrapideco,Frecuencia de muestreo,,Näytteenottotaajuus,Cadence de Sampling,,,サンプルレート,샘플ë§ë ˆì´íŠ¸,Steekproeftarief,CzÄ™stotliwość próbkowania,Taxa de amostragem,,,ЧаÑтота диÑкретизации,Фреквенција узорковања +HRTF,ADVSNDMNU_HRTF,,,,,,,,,,,,,,,머리전달함수,,HRTF,,,,, +OPL Synthesis,ADVSNDMNU_OPLSYNTHESIS,,,,Emulace OPL,OPL Synthese,,OPL-Sintezo,Síntesis OPL,,OPL-synteesi,Synthèse OPL,,,OPLシンセサイズ,OPL 합성,OPL synthese,Synteza OPL,Síntese OPL,,,Синтез OPL,OPL Ñинтеза +Number of emulated OPL chips,ADVSNDMNU_OPLNUMCHIPS,,,,PoÄet emulovaných OPL Äipů,Anzahl OPL Chips,,Nombro da imititaj OPL-blatoj,Número de chips OPL emulados,,Emuloitavien OPL-piirien lukumäärä,Puces OPL émulées,,Numero di chip OPL emulati,OPLãƒãƒƒãƒ—エミュレートã®ç•ªå·,ì—뮬레ì´íŠ¸ëœ OPL 칩 수,Aantal geëmuleerde OPL chips,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,,КоличеÑтво Ñмулируемых OPL чипов,Број емулираних OPL чипа +Full MIDI stereo panning,ADVSNDMNU_OPLFULLPAN,,,,Plné MIDI stereo,Echte MIDI-Stereoeffekte,,Tuta MIDI-sterepanoramado,Balance estéreo MIDI completo,,Täysi MIDI-stereopanorointi,Latéralisation complète MIDI,,,Full MIDIステレオパンニング,완전한 MIDI 스테레오 패ë‹,Volledige MIDI stereo panning,PeÅ‚ne efekty stereo dla MIDI,Lateralidade estéreo completa para MIDI,,,ÐŸÐ¾Ð»Ð½Ð°Ñ Ñтереопанорама Ð´Ð»Ñ MIDI,Пуно MIDI Ñтерео каналиÑање +OPL Emulator Core,ADVSNDMNU_OPLCORES,,,,EmulaÄní jádro OPL,OPL Emulatorkern,,OPL Imitilkerno,Núcleo de emulador OPL,,OPL-emulaattoriydin,CÅ“ur émulateur OPL,,,OPL エミュレート コア,OPL ì—뮬레ì´í„° 코어,OPL Emulator Kern,RdzeÅ„ Emulatora OPL,Núcleo do emulador de OPL,,,Ядро ÑмулÑции OPL,OPL језгро емулације +MIDI voices,ADVSNDMNU_MIDIVOICES,,,,PoÄet MIDI hlasů,MIDI Stimmen,,MIDI Voĉoj,Voces MIDI,,MIDI-äänet,Voix MIDI,,Voci MIDI,MIDI ボイス,MIDI 최대 ìŒìƒ‰ ì–‘,MIDI-stemmen,GÅ‚osy MIDI,Vozes MIDI,,,MIDI-голоÑа,MIDI глаÑови +FluidSynth,ADVSNDMNU_FLUIDSYNTH,,,,,,,,,,,,,,,,,,,,,, +Patch set,ADVSNDMNU_FLUIDPATCHSET,,,,Nástrojová sada,Patch-Set,,Flikaro,Set de parche,,Patch-asetus,Banque de Sons,,,パッムセット,패치 세트,,Zestaw patchów,Banco de sons,,,Патч-набор,Печ Ñет +Gain,ADVSNDMNU_FLUIDGAIN,,,,Zesílení,Relative Lautstärke,,Akiro,Ganancia,,Vahvistus,,,,ゲイン,쌓기,Relatief volume,Wzmocnienie,Ganho,,,УÑиление,Појачање +Reverb,ADVSNDMNU_REVERB,,,,OzvÄ›na,Hall,,Resono,Reverberación,,Kaiku,Réverbération,,,リãƒãƒ¼ãƒ–,리버브,Nagalm,PogÅ‚os,Reverberação,,,РеверберациÑ,Одјек +Reverb Level,ADVSNDMNU_REVERB_LEVEL,,,,Intenzita ozvÄ›ny,Hallintensität,,Resono-nivelo,Nivel de Reverberación,,Kaiunvoimakkuus,Niveau Réverb.,,,リãƒãƒ¼ãƒ–é‡,리버브 ê°•ë„,Nagalm niveau,Poziom pogÅ‚osu,Nível de reverberação,,,Уровень реверберации,Ðиво одјека +Chorus,ADVSNDMNU_CHORUS,,,,,,,Koruso,,,,,,,コーラス,코러스,,,,,,ХоруÑ,ÐšÐ¾Ñ€ÑƒÑ +Timidity++,ADVSNDMNU_TIMIDITY,,,,,,,,,,,,,,,,,,,,,, +ADLMidi,ADVSNDMNU_ADLMIDI,,,,,,,,,,,,,,,,,,,,,, +OPNMidi,ADVSNDMNU_OPNMIDI,,,,,,,,,,,,,,,,,,,,,, +Timidity config file,ADVSNDMNU_TIMIDITYCONFIG,,,,KonfiguraÄní soubor Timidity,Timidity Konfigurationsdatei,,Agordo-arkivo por Timidity,Ruta al archivo config. Timidity,,Timidity-config-tiedosto,Fichier de config. TiMidity,,File Timidity config,Timidity コンフィグファイル,Timidity 코딩 파ì¼,Timidity++ configuratiebestand,Plik konfiguracyjny Timidity,Arquivo de configuração do Timidity,,,Файл конфигурации Timidity,Timidity конфигурациона датотека +Relative volume,ADVSNDMNU_TIMIDITYVOLUME,,,,Relativní hlasitost,Relative Lautstärke,,Relativa volumeno,Volumen relativo,,Suhteellinen äänenvoimakkuus,Volume Relatif,,Volume relativo,相対音é‡,비êµì ì¸ 볼륨,Relatief volume,WzglÄ™dna gÅ‚oÅ›ność,Volume relativo,,,ОтноÑÐ¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾ÑÑ‚ÑŒ,Релативна јачина +WildMidi,ADVSNDMNU_WILDMIDI,,,,,,,,,,,,,,,,,,,,,, +WildMidi config file,ADVSNDMNU_WILDMIDICONFIG,,,,KonfiguraÄní soubor WildMidi,WilfMidi Konfigurationsdatei,,WildMidi agordarkivo,Archivo de config. WildMidi,,WildMidi-config-tiedosto,Fichier config. WildMidi,,File WildMidi config,WildMidi コンフィグファイル,WildMidi 코딩 파ì¼,WildMidi configuratiebestand,Plik konfiguracyjny WildMidi,Arquivo de configuração do WildMidi,,,Файл конфигурации WildMidi,WildMidi конфигурациона датотека +Select configuration,ADVSNDMNU_SELCONFIG,,,,Vybrat konfiguraci,Konfiguration wählen,,Elekti agordojn,Seleccionar configuración,,Valitse kokoonpano,Sélectionner configuration,,Seleziona la configurazione,構æˆé¸æŠž,ì„¤ì •ì„ ê³ ë¥´ì‹œì˜¤,Selecteer configuratie,Wybierz konfiguracjÄ™,Selecionar configuração,,,Выбор конфигурации,Изабери конфигурацију +Global,ADVSNDMNU_GLOBAL,,,,Globální,,,Malloka,Global,,Yleinen,,,Globale,グローãƒãƒ«,ì „ë°˜ì ,Globaal,Globalne,,,,Общие,Глобално +Freeverb,ADVSNDMNU_FREEVERB,,,,,,,,,,,,,,フリーãƒãƒ¼ãƒ–,프리버브,,,,,,, +Global Freeverb,ADVSNDMNU_GLOBAL_FREEVERB,,,,Globální Freeverb,Globales Freeverb,,Malloka Freeverb,Freeverb Global,,Yleinen Freeverb,Freeverb Global,,Freeverb globale,グローãƒãƒ« フリーãƒãƒ¼ãƒ–,ì „ë°˜ì  í”„ë¦¬ë²„ë¸Œ,Globale Freeverb,Globalny Freeverb,Freeverb Global,,,Глобальный Freeverb,Глобални Freeverb +Advanced Resampling,ADVSNDMNU_ADVRESAMPLING,,,,PokroÄilé pÅ™evzorkování,Erweitertes Resampling,,Altnivela respecimenado,Resampleo Avanzado,,Kehittynyt näytteenottotaajuuden muuntaminen,Resampling Avancé,,Resampling avanzato,高度ãªãƒªã‚µãƒ³ãƒ—リング,í–¥ìƒëœ 리샘플ë§,Geavanceerde herbemonstering,Zaawansowane Próbkowanie,Reamostragem Avançada,,,Продвинутый реÑÑмплинг,Ðапредно реÑампловање +OPL Bank,ADVSNDMNU_OPLBANK,,,,OPL sada,,,Banko por OPL,Banco OPL,,OPL-pankki,Banque OPL,,,,OPL ë±…í¬,,Bank OPL,Banco OPL,,,Банк OPL,OPL банка +OPL Emulator Core,ADVSNDMNU_ADLOPLCORES,,,,EmulaÄní jádro OPL,OPL Emulatorkern,,Imitilkerno por OPL,Núcleos de Emulador OPL,,OPL-emulaattoriydin,CÅ“ur Emulateur OPL,,,OPL エミュレートコア,OPL ì—뮬레ì´í„° 코어,OPL Emulator Kern,RdzeÅ„ Emulatora OPL,Núcleo do Emulador de OPL,,,Ядро ÑмулÑции OPL,OPL емулационо језгро +Run emulator at PCM rate,ADVSNDMNU_RUNPCMRATE,,,,Emulátor používá PCM vzorkovací frekvenci,Emulator benutzt PCM Samplerate,,Kurigi imitilon laÅ­ rapido de PCM,Ejecutar emulador a velocidad PCM,,Aja emulaattoria PCM-taajuudella,Emulateur utilise cadence PCM,,Esegui l'emulatore con rate PCM,PCMレートã§ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆå®Ÿè¡Œ,PCM ì†ë„ë¡œ ì—뮬레ì´í„° 실행,Emulator maakt gebruik van PCM Samplerate,Uruchom emulator w czÄ™stotliwoÅ›ci PCM,Rodar emulador em taxa PCM,,,ИÑпользовать Ñ Ñ‡Ð°Ñтотой PCM,Покрени емулацију на PCM Ñтопи +Number of emulated OPL chips,ADVSNDMNU_ADLNUMCHIPS,,,,PoÄet emulovaných OPL Äipů,Anzahl OPL Chips,,Numbro da imitaj OPL-blatoj,Número de chips OPL emulados,,Emuloitavien OPL-piirien lukumäärä,Puces OPL émulées,,Numero di chip OPL emulati,OPLãƒãƒƒãƒ—エミュレートã®ç•ªå·,ì—뮬레ì´íŠ¸ëœ OPL 칩 개수,Aantal geëmuleerde OPL chips,Liczba emulowanych czipów OPL,Número de chips OPL emulados,,,КоличеÑтво Ñмулируемых чипов OPL,Број емулираних OPL чипова +Volume model,ADVSNDMNU_VLMODEL,,,,Model hlasitosti,Lautstärkemodell,,Volumen-modelo,Modelo de Volumen,,Äänenvoimakkuusmalli,Modèle de Volume,,Modello di volume,音é‡ãƒ¢ãƒ‡ãƒ«,ëª¨ë¸ ë³¼ë¥¨,Volume model,Model gÅ‚oÅ›noÅ›ci,Modelo de volume,,,Модель громкоÑти,ВолумÑки модел +Aliasing,OPTVAL_ALIASING,,,,,,,Kromnomado,,,,,,,エイリアシング,ì—ì¼ë¦¬ì–´ì‹±,,,,,,ÐлиаÑинг,Преклапање +Linear,OPTVAL_LINEAR_1,This setting is duplicated threefold in order to allow for different grammatical gender endings,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,,Lineare,リニア,선형,Lineair,Liniowy,,,,Линейное,Линеаран +Linear,OPTVAL_LINEAR_2,,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,,Lineare,リニア,선형,Lineair,Liniowa,,,,ЛинейнаÑ,Линеаран +Linear,OPTVAL_LINEAR_3,,,,Lineární,,,Lineara,Lineal,,Lineaarinen,Linéaire,,Lineare,リニア,선형,Lineair,Liniowe,,,,Линейный,Линеаран +Nearest,OPTVAL_NEAREST,,,,Nejbližší,Nächster Nachbar,,Plej proksima,Cercano,,Lähin,Nearest,,Il più vicino,最寄り,가까ì´,Naast,Najbiższe,Vizinho mais próximo,,,Ближайший,Ðајближе +PCF (Low),OPTVAL_PCF_LOW,,,,PCF (nízké),PCF (niedrig),,PCF (Malata),PCF (Bajo),,PCF (matala),PCF (Low),,PCF (basso),PCF (低),PCF (하급),PCF (Laag),PCF (Niski),PCF (Baixo),,,PCF (низкий),PCF (ниÑко) +PCF (Medium),OPTVAL_PCF_MEDIUM,,,,PCF (stÅ™ední),PCF (mittel),,PCF (Meza),PCF (Medio),,PCF (keskitaso),PCF (Medium),,PCF (medio),PCF (中),PCF (중급),PCF (Medium),PCF (Åšredni),PCF (Médio),,,PCF (Ñредний),PCF (Ñредње) +PCF (High),OPTVAL_PCF_HIGH,,,,PCF (vysoké),PCF (hoch),,PCF (Alta),PCF (Alto),,PCF (korkea),PCF (High),,PCF (alto),PCF (高),PCF (ìƒê¸‰),PCF (Hoog),PCF (Wysoki),PCF (Alto),,,PCF (выÑокий),PCF (виÑоко) +Cubic,OPTVAL_CUBIC,,,,Kubická,Kubisch,,Kuba,Cúbico,,Kuutio,Cubique,,Cubico,キュービック,íë¹…,Kubieke,SzeÅ›cienny,Cúbico,,,КубичеÑкое,Кубан +Band-limited step,OPTVAL_BLEP,,,,Omezené krokování,Bandbegrenzte Schritte,,Bendo-limigita paÅo,Paso limitado por banda,,Kaistarajoitettu askel,Step limité par bande,,Passo limitato dalla banda,帯域制é™ã‚¹ãƒ†ãƒƒãƒ—,ì œí•œëœ ë‹¨ê³„ë³„ ë°´ë“œ,Bandbeperkte stap,Krok ograniczony pasmem,Passo limitado por banda,,,Пошаговое ограничение чаÑтоты,ПоÑтепено ограничење фреквенције +Linear (Slower),OPTVAL_LINEARSLOW,,,,Lineární (pomalejší),Linear (langsamer),,Lineara (Pli malrapida),Lineal (más lento),,Lineaarinen (hitaampi),Linéaire (Lent),,Lineare (più lento),リニア(é…ã‚),선형 (ëŠë¦¬ê²Œ),Lineair (langzamer),Liniowy (wolniejszy),Linear (Mais lento),,,Линейное (медленнее),Линеаран (Ñпорије) +Band-limited linear,OPTVAL_BLAM,,,,Omezená lineární,Bandbegrenzt linear,,Bendo-limigita lineara,Lineal limitado por banda,,Kaistarajoitettu lineaarinen,Linéaire limité par bande,,Lineare limitato dalla banda,帯域制é™ãƒªãƒ‹ã‚¢,ë°´ë“œ 제한 ì‹ ì„ í˜•,Band-beperkt lineair,Liniowy ograniczony pasmem,Linear limitado por banda,,,Линейное ограничение чаÑтоты,Линеарно ограничење фреквенције +Cubic (Slower),OPTVAL_CUBICSLOW,,,,Kubická (pomalejší),Kubisch (langsamer),,Kuba (Pli malrapida),Cúbico (más lento),,Kuutio (hitaampi),Cubique (Lent),,Cubico (più lento),キュービック (é…ã‚),íë¹… (ëŠë¦¬ê²Œ),Kubieke (langzamer),SzeÅ›cienny (wolniejszy),Cúbico (Mais lento),,,КубичеÑкое (медленнее),Кубан (Ñпорије) +Sinc,OPTVAL_SINC,,,,,,,,Seno cardinal,,,,,,シンク,싱í¬,,,,,,Кардинальный ÑинуÑ,Синк +Note on/off only,OPTVAL_NOTEONOFFONLY,,,,Pouze zaÄátek/konec noty,Nur für Note an/aus ,,Nur noton aktivigi/malatkivigi,Sólo notas de Activ./Desact.,,Vain nuotti päällä/pois,Note on/off seulement,,Note solamente ON/OFF,ノート オン/オフ ã®ã¿,노트를 ë„거나 ì¼°ì„ ë•Œ,Alleen toon aan/uit,Tylko dla wÅ‚Ä…czonych/wyÅ‚Ä…czonych notatek,Somente notas lig./deslig.,,,Только при включении/отключении нот,Само током укључења/иÑкључења ноте +Full ramping,OPTVAL_FULLRAMPING,,,,Plný nábÄ›h,,,Plena rampante,Aumento completo,,Täysi kerrytys,Rampe complète,,Ramping completo,フルランピング,최대 램핑,Volledige helling,PeÅ‚ne zwiÄ™kszenie,Rampa completa,,,Полное наращивание,Пуно појачање +Module Replayer Options,MODMNU_TITLE,,,,Nastavení pÅ™ehrávaÄe modulů,Modul-Spieler-Optionen,,Agordoj por Modulo-reludilo,Opciones de reproductor de módulos,,Moduulisoitinasetukset,Options Lecteur de Module,,Opzioni Module replayer,モジュールリプレイヤー オプション,모듈 ìž¬ìƒ ì„¤ì •,Module Speler Opties,Opcje Odtwarzacza Modułów,Opções de Reprodutor de Módulos,,,Параметры воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð´ÑƒÐ»ÐµÐ¹,Подешавања модуларног реплејера +Master volume,MODMNU_MASTERVOLUME,,,,Celková hlasitost,Grundlautstärke,,Ĉefvolumeno,Volumen maestro,,Yleisäänenvoimakkuus,Volume maître,,Volume master,全体音é‡,마스터 볼륨,Hoofdvolume,CaÅ‚kowita gÅ‚oÅ›ność,Volume master,,,ÐžÐ±Ñ‰Ð°Ñ Ð³Ñ€Ð¾Ð¼ÐºÐ¾ÑÑ‚ÑŒ,Глацни звук +Quality,MODMNU_QUALITY,,,,Kvalita,Qualität,,Kvaliteco,Calidad,,Laatu,Qualité,,Qualità,クオリティ,품질,Kwaliteit,Jakość,Qualidade,,,КачеÑтво,Квалитет +Volume ramping,MODMNU_VOLUMERAMPING,,,,KÅ™ivka hlasitosti,Lautstärkeverhalten,,Volumeno-pligrandigado,Aumento gradual de Volumen,,Äänenvoimakkuuden kertyminen,Rampe du volume,,Ramping volume,音é‡ãƒ©ãƒ³ãƒ”ング,볼륨 램핑,Volume-aanvulling,ZwiÄ™kszenie gÅ‚oÅ›noÅ›ci,Rampa de volume,,,Ðаращивание громкоÑти,Појачавање звука +Chip-o-matic,MODMNU_CHIPOMATIC,,,,,,,,,,,,,,ãƒãƒƒãƒ— オー マãƒãƒƒã‚¯,칩-오-매틱,,,,,,, +Global,ADVSNDMNU_GLOBAL,,,,Globální,,,Malloka,Global,,Yleinen,,,Globale,グローãƒãƒ«,ì „ë°˜ì ,Globaal,Globalne,,,,Общие,Глобално +Freeverb,ADVSNDMNU_FREEVERB,,,,,,,,,,,,,,フリーãƒãƒ¼ãƒ–,프리버브,,,,,,, +Global Freeverb,ADVSNDMNU_GLOBAL_FREEVERB,,,,Globální Freeverb,Globales Freeverb,,Malloka Freeverb,Freeverb Global,,Yleinen Freeverb,Freeverb Global,,Freeverb globale,グローãƒãƒ« フリーãƒãƒ¼ãƒ–,ì „ë°˜ì  í”„ë¦¬ë²„ë¸Œ,Globale Freeverb,Globalny Freeverb,Freeverb Global,,,Глобальный Freeverb,Глобални Freeverb +FluidSynth,ADVSNDMNU_FLUIDSYNTH,,,,,,,,,,,,,,,,,,,,,, +Patch set,ADVSNDMNU_FLUIDPATCHSET,,,,Nástrojová sada,Patch-Set,,Flikaro,Set de parche,,Patch-asetus,Banque de Sons,,,パッムセット,패치 세트,,Zestaw patchów,Banco de sons,,,Патч-набор,Печ Ñет +Gain,ADVSNDMNU_FLUIDGAIN,,,,Zesílení,Relative Lautstärke,,Akiro,Ganancia,,Vahvistus,,,,ゲイン,쌓기,Relatief volume,Wzmocnienie,Ganho,,,УÑиление,Појачање +Reverb,ADVSNDMNU_REVERB,,,,OzvÄ›na,Hall,,Resono,Reverberación,,Kaiku,Réverbération,,,リãƒãƒ¼ãƒ–,리버브,Nagalm,PogÅ‚os,Reverberação,,,РеверберациÑ,Одјек +Reverb Level,ADVSNDMNU_REVERB_LEVEL,,,,Intenzita ozvÄ›ny,Hallintensität,,Resono-nivelo,Nivel de Reverberación,,Kaiunvoimakkuus,Niveau Réverb.,,,リãƒãƒ¼ãƒ–é‡,리버브 ê°•ë„,Nagalm niveau,Poziom pogÅ‚osu,Nível de reverberação,,,Уровень реверберации,Ðиво одјека +Chorus,ADVSNDMNU_CHORUS,,,,,,,Koruso,,,,,,,コーラス,코러스,,,,,,ХоруÑ,ÐšÐ¾Ñ€ÑƒÑ +Timidity++,ADVSNDMNU_TIMIDITY,,,,,,,,,,,,,,,,,,,,,, +Sound enabled,SNDMNU_SNDENABLED,,,,,Sound aktiv,,,,,,,,,,,,,,,,, +Music enabled,SNDMNU_MUSENABLED,,,,,Musik aktiv,,,,,,,,,,,,,,,,, +CD Music Emulation,SNDMNU_CDEMU,,,,,CD-Musik-Emulation,,,,,,,,,,,,,,,,, +Sound Ambience,SNDMNU_AMBIENCE,,,,,Umgebungsgeräusche,,,,,,,,,,,,,,,,, +"Player Speech +",SNDMNU_SPEECH,,,,,Spielerkommentare,,,,,,,,,,,,,,,,, +Flip Stereo Channels,ADVSNDMNU_FLIPSTEREO,,,,,Stereo Kanäle vertauschen,,,,,,,,,,,,,,,,, +MAME OPL2,OPTVAL_MAMEOPL2,,,,,,,,,,,,,,,마메 OPL2,,,,,,, +DOSBox OPL3,OPTVAL_DOSBOXOPL3,,,,,,,,,,,,,,,ë„스박스 OPL3,,,,,,, +Java OPL3,OPTVAL_JAVAOPL3,,,,,,,,,,,,,,,ìžë°” OPL3,,,,,,, +Nuked OPL3,OPTVAL_NUKEDOPL3,,,,,,,,,,,,,,,,,,,,,, +,Video Mode,,,,,,,,,,,,,,,,,,,,,, +Video Mode,VIDMNU_TITLE,,,,Režim displeje,Videomodus,,Video-reÄimo,Modos de video,,Videotila,Mode Vidéo,,Modalità video,ビデオ 調整,화면 설정,Videomodus,Tryb Wideo,Modo de Vídeo,,,ÐаÑтройки видеорежима,Видео мод +Notebook Switchable GPU,DSPLYMNU_GPUSWITCH,,,,PÅ™epínatelné GPU pro notebooky,GPU Umschaltung für Notebooks,,Kajero ÅœanÄa GPU,GPU Altern. de Portátil,,Kannettavan kytkettävä grafiikkapiiri,GPU alternatif sur PC Portable,Váltható GPU laptopon,Scheda GPU Switchable per notebook,ノートブックGPU切替,ë…¸íŠ¸ë¶ ì„±ëŠ¥ ì¡°ì •,Notitieboekje schakelbare GPU,Zmiana GPU Notebooka,Placa de vídeo alternativa de notebook,,,ИÑпользование GPU ноутбука,КориÑти GPU ноутбук +Scaled (Nearest),OPTVAL_SCALENEAREST,,,,Å kálován (nejbližší),Skaliert (nächster Nachbar),,Skalita (Plej proksime),Escalado (Cercano),,Skaalattu (läheisin),Mis à l'échelle (Proche Voisin),,Scalato (più vicino),スケーリング (最寄り),확대 (ê°€ê¹ê²Œ),Geschaald (Dichtstbijzijnde),Przeskalowany (Najbliższy),Redimensionado (Vizinho mais próximo),Redimensionado (Apróximado),,МаÑштабировать (ближайшее),Скалиран (најближи) +Scaled (Linear),OPTVAL_SCALELINEAR,,,,Å kálován (lineární),Skaliert(linear),,Skalita (Linia),Escalado (Lineal),,Skaalattu (lineaarinen),Mis à l'échelle (Linéaire),,Scalato (lineare),スケーリング (リニア),확대 (선형 ì‹),Geschaald (Lineair),Przeskalowany (Liniowy),Redimensionado (Linear),,,МаÑштабировать (линейное),Скалиран (линеарно) +Letterbox,OPTVAL_LETTERBOX,,,,,,,Leterkesto,,,,,,Bande nere,レターボックス,레터박스,Brievenbus,,,,,Экранное каше,ПоштанÑко Ñандуче +Stretch,OPTVAL_STRETCH,,,,Roztažený,Strecken,,Streĉi,Estrechado,Estrecho,Venytetty,Etirer,,Disteso,伸縮,늘림,Rek,RozciÄ…gniÄ™ty,Esticado,,,РаÑÑ‚Ñнутый,РаÑтегнуто +Render Mode,VIDMNU_RENDERMODE,,,,Režim renderování,Rendermodus,,Bildigo-reÄimo,Modo de Renderizado,,Hahmonnustila,Mode de Rendu,,Modalità motore grafico,レンダラー,ë Œë”ë§ ì„¤ì •,Render Mode,Tryb Renderowania,Modo de Renderização,,,Режим рендеринга,Рендер мод +Fullscreen,VIDMNU_FULLSCREEN,,,,PÅ™es celou obrazovku,Vollbild,,Plena ekrano,Pantalla completa,,Koko näyttö,Plein écran,,Schermata piena,全画é¢,전체화면,Volledig scherm,PeÅ‚en Ekran,Tela cheia,Ecrã cheio,,Полный Ñкран,Цео екран +Retina/HiDPI support,VIDMNU_HIDPI,,,,Podpora Retiny/HiDPI,Retina/HDPI-Unterstützung,,Retino/HiDPI subteno,Soporte para Retina/HiDPI,,Retina/HiDPI-tuki,Support Retina/HiDPI ,Retina/HiDPI támogatás,Supporto Retina/HiDPi,Retina/HiDPI サãƒãƒ¼ãƒˆ,ë§ë§‰/하ì´DPI 활성화,Retina / HiDPI-ondersteuning,Wsparcie Retina/HiDPI,Suporte para Retina/HiDPI,,,Поддержка Retina/HiDPI,Retina/HiDPI подршка +Aspect ratio,VIDMNU_ASPECTRATIO,,,,PomÄ›r stran,Seitenverhältnis,,Ekran-proporcio,Relación de aspecto,,Kuvasuhde,Rapport D'Aspect,Képarány,Proporzioni,アスペクト比,종횡비,Beeldverhouding,Wpółczynnik proporcji,Proporção de tela,Proporção de ecrã,,Соотношение Ñторон,ÐžÐ´Ð½Ð¾Ñ Ð³Ð»ÐµÐ´Ð¸ÑˆÑ‚Ð° +Force aspect ratio,VIDMNU_FORCEASPECT,,,,Vynutit pomÄ›r stran,Erzwinge Seitenverhältnis,,Devigi ekran-proporcion,Forzar relación de aspecto,,Pakota kuvasuhde,Forcer Rapport,,Forza le proporzioni,アスペクト比ã«å¾“ã†,ê°•ì œ 종횡비,Geforceerde beeldverhouding,WymuÅ› współczynnik proporcji,Forçar proporção de tela,Forçar proporcção de ecrã,,Принудительное Ñоотношение Ñторон,ПриÑили Ð¾Ð´Ð½Ð¾Ñ Ð³Ð»ÐµÐ´Ð¸ÑˆÑ‚Ð° +Forced ratio style,VIDMNU_CROPASPECT,,,,Vynucený pomÄ›r stran,Modus für erzwungenes Seitenverhältnis,,Maniero por devigi proporcion,Relación de aspecto forzada,,Kuvasuhteen pakotustapa,Style de Ratio forcé,,Forza lo stile delle proporzioni,比率ã®å½¢å¼,ê°•ì œ 비율 스타ì¼,Gedwongen verhouding stijl,Wymuszony styl współczynnika,Forçar tipo de proporção,,,Тип принудительного ÑÐ¾Ð¾Ñ‚Ð½Ð¾ÑˆÐµÐ½Ð¸Ñ Ñторон,ПриÑиљен Ñтил одноÑа +Enable 5:4 aspect ratio,VIDMNU_5X4ASPECTRATIO,,,,Povolit pomÄ›r stran 5:4,Erlaube 5:4 Seitenverhältnis,,Aktivigi 5:4 ekran-proporcion,Activar relación de aspecto 5:4,,Ota käyttöön 5:4-kuvasuhde,Activer Rapport 5:4,5:4 képarány engedélyezése,Abilita le proporzioni 5:4,5:4アスペクト比をå¯èƒ½ã«ã™ã‚‹,5:4 비율 사용,Inschakelen 5:4 beeldverhouding,WÅ‚Ä…cz współczynnik proporcji 5:4,Habilitar proporção 5:4,,,Включить Ñоотношение Ñторон 5:4,Омогући 5:4 Ð¾Ð´Ð½Ð¾Ñ Ð³Ð»ÐµÐ´Ð¸ÑˆÑ‚Ð° +Resolution scale,VIDMNU_SCALEMODE,,,,Å kálování rozliÅ¡ení,Skalierung,,Distingivo-skalo,Escala de Resolución,,Resoluution skaalaus,Echelle de Résolution,,Scala di risoluzione,ç”»é¢ã‚¹ã‚±ãƒ¼ãƒ«,í•´ìƒë„ í¬ê¸°,Resolutie schaal,Skala rozdzielczoÅ›ci,Escala de resolução,,,МаÑштабирование,РезолуцијÑка Ñкала +Scale Factor,VIDMNU_SCALEFACTOR,,,,Faktor rozliÅ¡ení,Skalierungsfaktor,,Skalfaktoro,Factor de Escala,,Skaalauskerroin,Facteur d'échelle,,Fattore di scala,スケールå€çŽ‡,축척 펙터,Schaalfactor,Współczynnik Skali,Fator de escala,,,Значение маÑштаба,Фактор Ñкалирања +Use Linear Scaling (Fullscreen),VIDMNU_USELINEAR,,,,Použít lineární Å¡kálování (pÅ™es celou obrazovku),Lineare Skalierung (Vollbild),,Uzi Linian Skaladon (Plena ekrano),Usar Escalado Linear (Pant. Completa),,Lineaarinen skaalaus (koko näyttö),Mise à l'échelle Linéaire (Plein écran),,Usa lo scaling lineare (a schermo pieno),リニアスケールを使ã†(全画é¢),선형 스케ì¼ë§ 사용 (전체화면),Lineaire schaalverdeling gebruiken (volledig scherm),Użyj Liniowego Skalowania (PeÅ‚en Ekran),Usar escala linear (tela cheia),Usar escala linear (ecrã cheio),,Линейное маÑштабирование (полный Ñкран),КориÑти линеарно Ñкалирање (цео екран) +Custom Pixel Scaling,VIDMNU_CUSTOMRES,,,,Vlastní Å¡kálování pixelů,Benutzerdefinierte Skalierung,,Agorda bildero-skalo,Escalado de Pixel Personalizado,,Mukautettu skaalaus,Résolution Personalisée,,Scaling dei pixel personalizzato,カスタム ピクセルスケール,ì‚¬ìš©ìž ì§€ì • 픽셀 í¬ê¸° ì¡°ì •,Aangepaste Pixel Schaalvergroting,Niestandardowe Skalowanie Pikseli,Escala de Pixel Personalizada,,,МаÑштабирование пикÑелов,ПикÑел Ñкалирање +Custom Width,VIDMNU_CUSTOMX,,,,Vlastní šířka,Benutzerdefinierte Breite,,Agorda larÄo,Ancho Personalizado,,Mukautettu leveys,Largeur Personalisée,Egyéni szélesség,Lunghezza,カスタム å¹…,ì‚¬ìš©ìž ì§€ì • 너비,Aangepaste breedte,Niestandardowa Szerokość,Largura Personalizada,,,Длина,Ширина +Custom Height,VIDMNU_CUSTOMY,,,,Vlastní výška,Benutzerdefinierte Höhe,,Agorda alto,Alto Personalizado,,Mukautettu korkeus,Hauteur Personalisée,Egyéni magasság,Altezza,カスタム 高ã•,ì‚¬ìš©ìž ì§€ì • 높ì´,Aangepaste hoogte,Niestandardowa Wysokość,Altura Personalizada,,,Ð’Ñ‹Ñота,ВиÑина +Apply Changes (Windowed),VIDMNU_APPLYW,,,,Použít zmÄ›ny (v oknÄ›),Änderungen anwenden (Fenster),,Apliki ÅanÄojn (Fenestrito),Aplicar Cambios (ventana),,Ota käyttöön muutokset (ikkuna),Appliquer Changements (Fenêtre),,Applica le modifiche (a finestra),変更をé©ç”¨(ウィンドウ化),변경 ì ìš© (윈ë„ìš°),Wijzigingen toepassen (opgewonden),Zatwierdź Zmiany (Okno),Aplicar alterações (janela),,,Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ (оконный режим),Примени промене (прозор) +Apply Changes (Fullscreen),VIDMNU_APPLYFS,,,,Použít zmÄ›ny (pÅ™es celou obrazovku),Änderungen anwenden (Vollbild),,Apliki ÅanÄojn (Plena ekrano),Aplicar Cambios (Pant. Completa),,Ota käyttöön muutokset (koko näyttö),Appliquer Changements (Plein écran),,Applica le modifiche (a schermo pieno),変更をé©ç”¨(全画é¢åŒ–),변경 ì ìš© (전체화면),Wijzigingen toepassen (Volledig scherm),Zatwierdź Zmiany (PeÅ‚en Ekran),Aplicar alterações (tela cheia),Aplicar alterações (ecrã cheio),,Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ (полный Ñкран),Примени промене (цели екран) +Choose Resolution Preset,VIDMNU_RESPRESET,,,,Vybrat pÅ™ednastavené rozliÅ¡ení,Auflösungsvoreinstellung,,Elekti Agordaĵon por Distingivo,Seleccionar Preset de Resolución,,Valitse ennalta määritetty resoluutio,Choisir paramètre personalisé,,Scegli preset di risoluzione,解åƒåº¦ãƒ—リセットをé¸ã¶,í•´ìƒë„ 사전 설정 ì„ íƒ,Kies een vooraf ingestelde resolutie,Wybierz Zestaw RozdzielczoÅ›ci,Escolher Resolução Predefinida,,,Выбор преÑета разрешениÑ,РезолуцијÑка подешавања +Custom Resolution Presets,VIDMNU_RESPRESETTTL,,,,Vlastní pÅ™ednastavení rozliÅ¡ení,Benutzerdefinierte Auflösungsvoreinstellungen,,LaÅ­mendaj agordaĵoj por Distingivo,Seleccionar Preset de Resoluciones,,Ennalta määritetyt mukautetut resoluutiot,Résolutions Personalisée,,Preset di risoluzione personalizzati,カスタム解åƒåº¦ãƒ—リセット,ì‚¬ìš©ìž ì§€ì • í•´ìƒë„ 미리 ì¡°ì •,Vooraf ingestelde aangepaste resolutie,Niestandardowe Zestawy RozdzielczoÅ›ci,Predefinições Personalizadas,,,ПользовательÑкие преÑеты,РезолуцијÑка подешавања +Preset Resolution Modes,VIDMNU_RESPRESETHEAD,,,,PÅ™ednastavená rozliÅ¡ení,Vordefinierte Auflösungsmodi,,Agordaĵaj DistingivreÄimoj,Modos de Preset de Resolución,,Ennalta määritetyt resoluutiotilat,Choisir mode de Résolution,,Modalità preset di risoluzione,解åƒåº¦ãƒ¢ãƒ¼ãƒ‰ã®èª¿æ•´,í•´ìƒë„ 미리 ì¡°ì • 모드,Vooraf ingestelde resolutie modi,Tryby Zestawów RozdzielczoÅ›ci,Modos de Resolução Predefinidas,,,ДоÑтупные разрешениÑ,ПоÑтављени резолуцијÑки модови +4:3 Aspect,VIDMNU_ASPECT43,,,,PomÄ›r stran 4:3,4:3 Seitenverhältnis,,4:3 Proporcio,Aspecto 4:3,,4:3-tilat,Rapport 4:3,,Aspetto 4:3,4:3アスペクト比,4:3 비율,,Proporcje 4:3,Proporção 4:3,,,Соотношение Ñторон 4:3,4:3 гледиште +5:4 Aspect,VIDMNU_ASPECT54,,,,PomÄ›r stran 5:4,5:4 Seitenverhältnis,,5:4 Proporcio,Aspecto 5:4,,5:4-tilat,Rapport 5:4,,Aspetto 5:4,5:4アスペクト比,5:4 비율,,Proporcje 5:4,Proporção 5:4,,,Соотношение Ñторон 5:4,5:4 гледиште +16:9 Aspect,VIDMNU_ASPECT169,,,,PomÄ›r stran 16:9,16:9 Seitenverhältnis,,16:9 Proporcio,Aspecto 16:9,,16:9-tilat,Rapport 16:9,,Aspetto 16:9,16:9アスペクト比,16:9 비율,,Proporcje 16:9,Proporção 16:9,,,Соотношение Ñторон 16:9,16:9 гледиште +16:10 Aspect,VIDMNU_ASPECT1610,,,,PomÄ›r stran 16:10,16.10 Seitenverhältnis,,16:10 Proporcio,Aspecto 16:10,,16:10-tilat,Rapport 16:10,,Aspetto 16:10,16:10アスペクト比,16:10 비율,,Proporcje 16:10,Proporção 16:10,,,Соотношение Ñторон 16:10,16:10 гледиште +Max FPS,VIDMNU_MAXFPS,,,,,,,,,,,,,,,,,,,,,, +Unlimited,OPTVAL_UNLIMITED,,,,,Unlimitiert,,,,,,,,,,,,,,,,, +60 fps,OPTVAL_60FPS,,,,,,,,,,,,,,,,,,,,,, +75 fps,OPTVAL_75FPS,,,,,,,,,,,,,,,,,,,,,, +90 fps,OPTVAL_90FPS,,,,,,,,,,,,,,,,,,,,,, +120 fps,OPTVAL_120FPS,,,,,,,,,,,,,,,,,,,,,, +144 fps,OPTVAL_144FPS,,,,,,,,,,,,,,,,,,,,,, +200 fps,OPTVAL_200FPS,,,,,,,,,,,,,,,,,,,,,, +,Miscellaneous Options,,,,,,,,,,,,,,,,,,,,,, +Miscellaneous Options,MISCMNU_TITLE,,,,Ostatní nastavení,Verschiedene Optionen,,Ekstraĵa agordoj,Opciones Misceláneas,,Sekalaiset asetukset,Options Annexes,,Opzioni miste,ãã®ä»–ã®ã‚ªãƒ—ション,ê·¸ 외 설정,Diverse opties,Różne Opcje,Outras Opções,,,Дополнительные наÑтройки,Разна подешавања +Merge left+right Alt/Ctrl/Shift,MISCMNU_MERGEKEYS,,,,Zkombinovat pravý a levý Alt/Ctrl/Shift,Linke und rechte Umschalt/Strg/Alt zusammenfassen,,Kunigi maldekstro+dekstro Alt/Ctrl/Shift,Combinar izq.+der. Alt/Ctrl/Mayús,,Yhdistä vasen ja oikea Alt/Ctrl/Vaihto,Combiner Alt/Ctrl/maj gauche & droite,,Unisci sinistra+destra Alt/Control/Maiusc,å·¦ã¨å³ã®ALT/CTRL/SHIFTキーを統åˆ,양쪽 ALT/CTRL/SHIFT키 합병,Samenvoegen links+rechts Alt/Ctrl/Shift,PoÅ‚Ä…cz przyciski lewo+prawo Alt/Ctrl/Shift,Unir teclas Alt/Ctrl/Shift esquerdas e direitas,Juntar Alt/Ctrl/Shift esquerdo+direito,,Ðе разделÑÑ‚ÑŒ левый/правый ALT/CTRL/SHIFT,Споји лево+деÑно Ðlt/Ctrl/Shift +Alt-Enter toggles fullscreen,MISCMNU_WINFULLSCREENTOGGLE,,,,Alt-Enter pÅ™epíná celou obrazovku,Alt-Enter schaltet Vollbild an/aus,,Alt klavo-Enter klavo baskuligi tutekranon,Alt+Enter alterna pantalla completa,,Alt-Enter kytkee täyden ruudun päälle/pois,Alt-Entrée alterne plein écran,,Alt-Invio attiva/disattiva lo schermo pieno,ALTã¨ENTERã§å…¨ç”»é¢ã«åˆ‡ã‚Šæ›¿ãˆ,ALT+ENTER키로 전체화면 ì¡°ì •,Alt-Enter schakelt het volledige scherm aan/uit,Alt-Enter przeÅ‚Ä…cza na peÅ‚en ekran,Alt-Enter ativa tela cheia,Alt-Enter ativa ecrã cheio,,Переключение полного Ñкрана по ALT+ENTER,Alt-Enter пребацује на цео екран +Command-F toggles fullscreen,MISCMNU_MACFULLSCREENTOGGLE,,,,Command-F pÅ™epíná celou obrazovku,Cmd-F schaltet Vollbild an/aus,,Komando-F baskuligi tutekranon,Cmd-F alterna pantalla completa,,Komento-F kytkee täyden ruudun päälle/pois,Command-F alterne plein écran,,Command-F attiva/disattiva lo schermo pieno,Ctrl + Fキーã§å…¨ç”»é¢è¡¨ç¤º,COMMAND+F키로 전체화면 ì¡°ì •,Command-F schakelt het volledige scherm aan/uit,Command-F przeÅ‚Ä…cza peÅ‚ny ekran,Command-F ativa tela cheia,Command-F ativa ecrã cheio,,Переключение полного Ñкрана по Command+F,Command-F пребацује на цео екран +Show game selection dialog,MISCMNU_QUERYIWAD,,,,Zobrazit dialog pro výbÄ›r GRPu,Zeige Spielauswahl,,Montri GRP elekta dialogo,Mostrar diálogo de selección de GRP,,Näytä GRP-valintaikkuna,Afficher la séléction de jeu,,Mostra la schermata della selezione GRP,GRPã®é¸æŠžç”»é¢ã‚’表示,GRP 게임 ì„ íƒì°½ 표시,GRP-selectiedialoogvenster weergeven,Pokaż ekran wyboru gry,Mostrar janela de seleção de jogo.,,,Выбор GRP-файла при запуÑке,Покажи GRP дијалог за избор +Enable cheats from all games,MISCMNU_ALLCHEATS,,,,Povolit cheaty ze vÅ¡ech her,Ermögliche Cheats aus allen Spielen,,Aktivigi trompojn el tutaj ludoj,Activar trucos de todos los juegos,,Ota käyttöön huijauskoodit kaikista peleistä,Activer cheats de tous les jeux,,Abilita tutti i cheat da tutti i giochi,全ゲームã§ãƒãƒ¼ãƒˆä½¿ç”¨å¯ã«ã™ã‚‹,모든 ê²Œìž„ì— ì¹˜íŠ¸ 허용,Laat bedriegers van alle spellen toe,WÅ‚Ä…cz oszustwa ze wszystkich gier,Habilitar trapaças de todos os jogos,Permitir batotas de todos os jogos,,Читы из вÑех игр,Омогући читове од Ñвих игара +Enable autosaves,MISCMNU_ENABLEAUTOSAVES,,,,Povolit automatické ukládání,Automatisches Speichern,,Aktivigi aÅ­tokonservojn,Activar autoguardado,,Ota käyttöön automaattiset tallennukset,Activer Sauvegardes auto,,Abilita i salvataggi automatici,オートセーブを有効化,빠른 저장 허용,Automatisch opslaan inschakelen,WÅ‚Ä…cz autozapis,Habilitar salvamento automático,Permitir gravação automática,,ÐвтоÑохранениÑ,Омогући аутоÑејвове +Number of autosaves,MISCMNU_AUTOSAVECOUNT,,,,PoÄet automatických uložených her,Anzahl von automatischen Speicherständen,,Kvanto da aÅ­tokonservojn,Número de autoguardados,,Automaattisten tallennusten lukumäärä,Total de sauvegardes auto,,Numero di salvataggi automatici,オートセーブã®æœ€å¤§æ•°,빠른 저장 수,Aantal autosafes,Liczba autozapisów,Número de salvamentos automáticos,Número de gravações automáticos,,КоличеÑтво автоÑохранений,Број аутоматÑких чувања +Save/Load confirmation,MISCMNU_SAVELOADCONFIRMATION,,,,Potvrzení o uložení/naÄtení,Laden/Speichern bestätigen,,Konservi/ÅœarÄi jesigo,Confirmación al guardar/cargar,,Tallennuksen/Latauksen vahvistus,Confirmation C/S,,Conferma Salvataggio/Caricamento,セーブ/ロード時ã«ç¢ºèª,스í¬ë¦½íŠ¸ë¡œ 스í¬ë¦°ìƒ· ìƒì„± 허용,Opslaan/Laad bevestiging,Potwierdzenie zapisu/wczytania,Confirmação ao salvar/carregar,Confirmação ao gravar/carregar,,Подтверждение при Ñохранении/загрузке,Потврђивање током чувања/учитавања +Enable making screenshots by scripts,MISCMNU_ENABLESCRIPTSCREENSHOTS,,,,Povolit skriptům poÅ™izovat snímky obrazovky,"Erlaube Skripts, Screenshots zu machen",,Aktivigi faranto ekrankopiojn per skriptoj,Habilitar captura de pantalla por scripts,,Salli komentosarjoin otetut kuvakaappaukset,Autoriser les Scripts à prendre des captures,,Abilita la cattura dello schermo tramite scripts,スクリプトã‹ã‚‰ã®ã‚¹ã‚¯ã‚·ãƒ§ä½œæˆã‚’有効化,저장/불러오기 확ì¸,Screenshots maken met behulp van scripts,Pozwól na robienie zrzutów ekranu przez skrypty,Habilitar capturas de tela por scripts,Permitir capturas de ecrã por scripts,,ВозможноÑÑ‚ÑŒ делать Ñкриншоты через Ñкрипты,Омогући прављење Ñкриншотова по Ñкрипти +Load *.deh/*.bex lumps,MISCMNU_DEHLOAD,,,,NaÄítat *.deh/*.bex soubory,Lade *.deh/*.bex Daten,,ÅœarÄi *.deh/*.bex lumpoj,Cargar archivos *.deh/*.bex,,Lataa *.deh/*.bex-lump-tiedostot,Charger fichiers *.deh/*.bex,,Carica i lump *.deh/*.bex,.deh/.bexファイルを読ã¿è¾¼ã‚€,*.deh/*.bex 럼프 íŒŒì¼ ë¶ˆëŸ¬ì˜¤ê¸°,*.deh/*.bex laden,ZaÅ‚aduj dane *.deh/*.bex,Carregar lumps *.deh/*.bex,,,Загружать файлы *.deh/*.bex,Учитај *.deh/*.bex фајлове +Cache nodes,MISCMNU_CACHENODES,,,,Cachovat nodes,Nodes zwischenspeichern,,KaÅmemoraj nodoj,Caché de nodos,,Tallenna solmut välimuistiin,Mise en cache des nodes,,Cache dei nodi,ノードキャッシュ,ìºì‹œ 노드,Cache nodes,WÄ™zÅ‚y pamiÄ™ci podrÄ™cznej,Cachê de nodes,Cache de nodes,,КÑширование нодов,Кеширани чворови +Time threshold for node caching,MISCMNU_CACHETIME,,,,ÄŒasový práh pro cachování nodes,Zeitschwelle für das Zwischenspeichern von Nodes,,Templimo pro kaÅmemornodi,Umbral de tiempo para caché de nodos,,Kynnysaika solmujen välimuistitallennukseen,Limite cache des nodes,,Soglia di tempo per il caching dei nodi,ノードキャッシュ時間ã®é–¾å€¤,노드 ìºì‹±ì„ 위한 시간 임계값 계산,Tijdsdrempel voor het cachen van nodes,Próg czasowy buforowania wÄ™złów,Limite de tempo para cachê de nodes,Limite de tempo para cache de nodes,,Временной порог Ð´Ð»Ñ ÐºÑÑˆÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½Ð¾Ð´Ð¾Ð²,ВременÑки праг за кеширање чвора +Clear node cache,MISCMNU_CLEARNODECACHE,,,,VyÄistit node cache,Nodespeicher löschen,,ViÅi kaÅmemorajn nodojn,Limpiar Caché de nodos,,Tyhjennä solmuvälimuisti,Vider le cache des nodes,,Pulisci la cache dei nodi,ノードã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’クリア,노드 ìºì‹œë¥¼ ì‚­ì œ,Duidelijke node cache,Wyczyść pamięć podrÄ™cznÄ…,Limpar cachê de nodes,Limpar cache de nodes,,ОчиÑтить кÑш нодов,"Избриши кеширане чворове +" +Allow skipping of intermission scrollers,MISCMNU_INTERSCROLL,,,,Povolit pÅ™eskakování intermission posuvníků,Erlaube Ãœberspringen von Intermission-Scrollern,,Permesi transsalti interaktajn rulumojn,Permitir omisión de intermedios,,Salli tarinaruutujen vierityksen ohittaminen,Sauter compteurs d'intermission,,Consenti di saltare gli scorrimenti delle intermissioni,クリアçµæžœé›†è¨ˆã®ã‚¹ã‚­ãƒƒãƒ—を許å¯,ì¸í„°ë¯¸ì…˜ 스í¬ë¡¤ëŸ¬ ìƒëžµ 허용,,Pozwól na pominiÄ™cie wstawek,Pular telas de intervalo entre fases,Saltar ecrãs de intervalo entre níveis,,Разрешение пропуÑка текÑтовых вÑтавок,Дозволи преÑкакање прелаза Ñа текÑтовима +Scripts Only,OPTVAL_SCRIPTSONLY,,,,Pouze skripty,Nur Skripte,,Skriptoj Sole,Sólo scripts,,Vain komentosarjat,Scripts seulement,,Solo script,スクリプトã®ã¿,스í¬ë¦½íŠ¸ì—만,Alleen scripts,Tylko skrypty,Scripts apenas,,,Только Ñкрипты,Само Ñкрипте +Disable keyboard cheats,MISCMNU_NOCHEATS,,,,,Tastatur-Cheats deaktivieren,,Malaktivigi klavaran trumpon,Desactivar trucos por teclado,,,,,,キーボードã‹ã‚‰ã®ãƒãƒ¼ãƒˆç„¡åŠ¹,,Schakel cheats uit,,Desabilitar trapaças de teclado,,,, +Quicksave rotation,MISCMNU_QUICKSAVEROTATION,,,,Rotace rychle uložených her,Schnellspeicherrotation,,Rapidkonservado-rotacio,Rotación de Salvado Rápido,,Pikatallennuskierto,Rotation Sauvegardes Rapides,,Rotazione rapide della quicksave,クイックセーブ間隔,빠른 저장 간격,Roteer quicksaves,Rotacja szybkich zapisów,Rotação de quicksave,,,Чередовать Ñлоты Ð´Ð»Ñ Ð±Ñ‹Ñтрых Ñохранений,Окретање брзих чувања +Number of quicksaves in rotation,MISCMNU_QUICKSAVECOUNT,,,,PoÄet rychle uložených her v rotaci,Anzahl Schnellspeicherplätze,,Nombro da rapidkonservitaj ludoj en rotaciado,Número de Salvados Rápidos en Rotación,,Pikatallennusten määrä kierrossa,Nombre de sauvegardes en rotation,,Numero di quicksaves in rotazione,間隔クイックセーブã®æ•°,빠른 저장 ê°„ê²©ì˜ ìˆ˜,Aantal roterende quicksaves,Ilość szybkich zapisów w rotacji,Número de quicksaves em rotação,,,Кол-во Ñлотов Ð´Ð»Ñ Ð±Ñ‹Ñтрых Ñохранений,Број брзих чувања у окретању +Ninja Slice Animation,MISCMNU_NINJA,,,,,,,,,,,,,,,,,,,,,, +Use Darts instead of Shurikens,MISCMNU_DARTS,,,,,,,,,,,,,,,,,,,,,, +,Miscellaneous,,,,,,,,,,,,,,,,,,,,,, +"You are playing the shareware +version of Duke Nukem 3D. While +this version is really cool, you +are missing over 75% of the total +game, along with other great extras +which you'll get when you order +the complete version and get +the final three episodes.",BUYDUKE,,,,,,,,,,,,,,,,,,,,,, +"Buy the complete version of +Blood for three new episodes +plus eight BloodBath-only levels!",BUYBLOOD,,,,,,,,,,,,,,,,,,,,,, +"Loading and saving games +not supported +in this demo version of Blood.","BLOOD_SW_BLOCK +",,,,,,,,,,,,,,,,,,,,,, +"Are you sure you want to end the game? +",ENDGAME,,,,"Opravdu si pÅ™ejeÅ¡ ukonÄit hru? +","Willst du das Spiel wirklich beenden? +",,"Ĉu vi certas, ke vi volas fini la ludon? +","¿Estás segur@[ao_esp] que deseas cerrar el juego? +",,"Haluatko varmasti päättää pelin? +","Voulez vous mettre fin à votre partie? +","Biztos vagy benne hogy beakarod fejezni a játékot? +","Sei sicuro di voler terminare la partita? +","本当ã«ã‚²ãƒ¼ãƒ ã‚’中断ã™ã‚‹ã®ã‹? +","ê²Œìž„ì„ ì •ë§ë¡œ 종료하시겠습니까? +","Weet je zeker dat je het spel wilt beëindigen? +","Czy jesteÅ› pewien że chcesz zakoÅ„czyć grÄ™? +","Tem certeza que deseja encerrar este jogo? +","Tem certeza que deseja fechar este jogo? +",,"Ð’Ñ‹ дейÑтвительно хотите закончить игру? +","ЈеÑте ли Ñигурни да желите завршити игру? +" +Are you sure you want to quit this game?,CONFIRM_QUITMSG,,,,PÅ™ejeÅ¡ si odejít?,"Bist du dir sicher, dass du gehen willst?",,"Ĉu vi certas, ke vi volas ĉesi?",¿Estás segur@[ao_esp] que quieres salir?,,Haluatko varmasti lopettaa?,Êtes vous sûr de vouloir quitter ?,Biztos vagy benne hogy ki akarsz lépni?,Sei sicuro di voler abbandonare?,本当ã«çµ‚了ã™ã‚‹ã®ã‹?,ì •ë§ ì¢…ë£Œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?,Weet je zeker dat je wilt stoppen?,Czy jesteÅ› pewien że chcesz wyjść?,Tem certeza que quer sair?,Tens a certeza que queres sair?,,Ð’Ñ‹ дейÑтвительно желаете выйти?,Да ли Ñте Ñигурни да желите да одуÑтанеш? +Reset controls to defaults?,CONFIRM_CTRL1,,,,,Steuerung auf Standard zurücksetzen?,,,,,,,,,,,,,,,,, +Reset controls to classic defaults?,CONFIRM_CTRL2,,,,,Steuerung auf klassischen Standard zurücksetzen?,,,,,,,,,,,,,,,,, +Reset controls to left-handed defaults?,CONFIRM_CTRL3,,,,,Steuerung auf linkshändigen Standard zurücksetzen?,,,,,,,,,,,,,,,,, +,Obituaries,,,,,,,,,,,,,,,,,,,,,, +%k boned %o like a fish,TXT_OBITUARY1,,,,%o byl@[ao_cs] vykoÅ¡tÄ›n@[ao_cs] jako ryba hráÄem %k,%k hat %o zerlegt wie einen Fisch,,%k senostigis %o kiel fiÅon,%k deshuesó a %o como a un pescado,,%k perkasi %o paran kuin kalan,%k désossa %o comme un poisson,%k kifilézte %o -t mint a halat,%k ha dissossato %o come un pesce,%k 㯠%o ã®éª¨ã‚’é­šã®ã‚ˆã†ã«å¼•ã£ã“抜ã„ãŸã€‚,%k ì€(는) %o ì˜ ë¼ˆë¥¼ ë°œëžë‹¤.,%k uitgebeend %o zoals een vis,%k odfiletowaÅ‚@[ao_pl] %o jak rybÄ™,%k desossou %o como um peixe,,,Игрок %k переÑчитал коÑточки игрока %o,%k је очиÑтио %o као рибу +%k castrated %o,TXT_OBITUARY2,,,,%o byl@[ao_cs] vykastrován@[ao_cs] hráÄem %k,%k hat %o kastriert,,%k kastris %o,%k castró a %o,,%k kastroi %o paran,%k castra %o,%k kasztrálta %o -t,%k ha castrato %o,%k 㯠%o を去勢ã—ãŸã€‚,%k ì€(는) %o ì„(를) 거세시켰다.,%k gecastreerd %o,%k wykastrowaÅ‚@[ao_pl] %o,%k castrou %o,,,Игрок %k каÑтрировал игрока %o,%k је каÑтрирао %o +%k creamed %o,TXT_OBITUARY3,,,,%o byl@[ao_cs] rozÅ¡lehán@[ao_cs] hráÄem %k,%k hat %o eingeseift,,%k kremigis %o,%k cremó a %o,,%k kermasi %o paran,%k a battu %o à plate couture ,%k elkente %o -t,%k ha cremato %o,%k 㯠%o ã«ååブãƒæ’’ã‘ã•ã›ãŸã€‚,%k ì€(는) %o ì„(를) ì–‘ë…시켰다.,%k romed %o,%k spieniÅ‚@[ao_pl] %o,%k fez creme de %o,,,Игрок %k взбил игрока %o,%k је иÑтукао %o +%k decimated %o,TXT_OBITUARY4,,,,%o byl@[ao_cs] zdecimován@[ao_cs] hráÄem %k,%k hat %o dezimiert,,%k detruegis %o,%k diezmó a %o,,%k hävitti %o paran,%k a décimé %o,%k megtizedelte %o -t,%k ha decimato %o,%k 㯠%o ã®å±…場所を間引ã„ãŸã€‚,%k ì€(는) %o ì„(를) ë§ê°€ëœ¨ë ¸ë‹¤.,%k gedecimeerd %o,%k przetrzebiÅ‚@[ao_pl] %o,%k decimou %o,,,Игрок %k ÑкоÑил игрока %o,%k је деÑетковао %o +%k destroyed %o,TXT_OBITUARY5,,,,%o byl@[ao_cs] zniÄen@[ao_cs] hráÄem %k,%k hat %o zerstört,,%k detruis %o,%k destruyó a %o,,%k tuhosi %o paran,%k a détruit %o,%k elpusztította %o -t,%k ha distrutto %o,%k 㯠%o を完全ã«ç ´å£Šã—ãŸã€‚,%k ì€(는) %o ì„(를) 파괴했다.,%k vernietigd %o,%k zniszczyÅ‚@[ao_pl] %o,%k destruiu %o,,,Игрок %k уничтожил игрока %o,%k је уништио %o +%k diced %o,TXT_OBITUARY6,,,,%o byl@[ao_cs] nakrájen@[ao_cs] na kostiÄky hráÄem %k,%k hat %o in Würfel zerteilt,,%k diskubigis %o,%k picó en cubitos a %o,,%k pilkkosi %o paran,%k a coupé en dés %o,%k felkockázta %o -t,%k ha tagliato a cubetti %o,%k 㯠%o ã‚’è³½ã®ç›®ã«åˆ‡ã£ãŸã€‚,%k ì€(는) %o ì„(를) 잘게 잘게 ì°ì—ˆë‹¤.,%k in blokjes gesneden %o,%k pokroiÅ‚@[ao_pl] w kostkÄ™ %o,%k fez picadinho de %o,%k cortou %o,,Игрок %k разрезал игрока %o,%k је иÑецкао %o +%k disembowled %o,TXT_OBITUARY7,,,,%o byl@[ao_cs] vykuchán@[ao_cs] hráÄem %k,%k hat %o ausgeweidet,,%k sentripigis %o,%k destripó a %o,,%k suolisti %o paran,%k a étripé %o,%k kibelezve,%k ha smembrato %o,%k 㯠%o ã®è‡“物を引ããšã‚Šå‡ºã—ãŸã€‚,%k ì€(는) %o ì˜ ë‚´ìž¥ì„ ë„려냈다.,%k van de ingewanden gehaald %o,%k wypatroszyÅ‚@[ao_pl] %o,%k estripou %o,,,Игрок %k выпотрошил игрока %o,%k је ампутирао %o +%k flattened %o,TXT_OBITUARY8,,,,%o byl@[ao_cs] zplacatÄ›n@[ao_cs] hráÄem %k,%k hat %o dem Erdboden gleichgemacht,,%k platigis %o,%k aplanó a %o,,%k lyttäsi %o paran,%k a aplati %o,%k kilapítva,%k ha schiacciato %o,%k 㯠%o ã‚’ã¶ã£æ½°ã—ãŸã€‚,%k ì€(는) %o ì˜ ì½”ë¥¼ 납작하게 만들었다.,afgevlakt %k afgevlakt %o,%k rozpÅ‚aszczyÅ‚@[ao_pl] %o,%k achatou %o,%k espalmou %o,,Игрок %k ÑплюÑнул игрока %o,%k је изравнао %o +%k gave %o Anal Justice,TXT_OBITUARY9,,,,%o utržil@[ao_cs] anální spravedlnost od hráÄe %k,%k hat %o anale Gerechtigkeit gegeben,,%k donis %o puga ĵustico,%k le dió Justicia Anal a %o,,%k jakoi %o paralle anaalioikeutta,%k a rendu une justice anale a %o,%k %o -nak Anális Igazságot adott,%k ha dato a %o Giustizia Anale,%k 㯠%o ã®ã‚±ãƒ„ã«ã¶ã¡è¾¼ã‚“ã ã€‚,%k ì€(는) %o ì—게 í™ì½©í–‰ì„ 보냈다.,%k gaf %o Anaalrechtvaardigheid,%k daÅ‚@[ao_pl] %o AnalnÄ… Sprawiedliwość,%k deu Justiça Anal para %o,,,Игрок %k уÑтроил Ðнальное ПравоÑудие игроку %o,%k је дао %o аналну правду +%k gave AnAl MaDnEsS to %o,TXT_OBITUARY10,,,,%o utrpÄ›l@[ao_cs] AnÃlNí ŠíLeNsTvà od hráÄe %,%k gab %o AnAlEn WaHnSiNn,,%k donis pUgAn frEnEzOn al %o,%k le dió LoCuRa AnAl a %o,,%k teki %o paran AnAaLiHuLlUkSi,%k a donné la FOLIE ANALE a %o,%k %o -nak Seggbe Durrantott,%k ha dato FoLlIa AnAle a %o,%k 㯠%o ã®ã‚±ãƒ„をガãƒã‚¬ãƒã«ã—ãŸã€‚,%o ì€(는) %k ì˜ ì°°ì§„ ë§›ì„ ë³´ì•˜ë‹¤.,%k gaf AnAl MaDnEs aan %o,%k daÅ‚@[ao_pl] %o AnAlNe SzAlEÅ„StWo ,%k deu LoUcUrA aNaL para %o,,,Игрок %k уÑтроил ÐнÐЛ КаРнаВаЛ игроку %o,%k је дао ÐнÐлÐо ЛуДиЛо %o +%k killed %o,TXT_OBITUARY11,,,,%o byl@[ao_cs] zabit@[ao_cs] hráÄem %k,%k hat %o getötet,,%k mortigis %o,%k mató a %o,,%k tappoi %o paran,%k a tué %o,%k kicsinálta %o -t,%k ha ucciso %o,%k 㯠%o をブッ殺ã—ãŸã€‚,%k ì€(는) %o ì„(를) 죽였다.,%k gedood %o,%k zabiÅ‚@[ao_pl] %o,%k matou %o,,,Игрок %k убил игрока %o,%k је убио %o +%k made mincemeat out of %o,TXT_OBITUARY12,,,,%o byl@[ao_cs] namelen@[ao_cs] hráÄem %k,%k hat %o zu Hackfleisch verarbeitet,,%k faris mincemeat el %o,%k hizo picadillo de %o,,%k teki jauhelihaa %o parasta,%k a fait de la viande hachée de %o,%k darálthúst csinált %o -ból,%k ha triturato %o,%k 㯠%o をミンãƒã«ã—ãŸã€‚,%o ì€(는) %k ì— ì˜í•´ 분쇄ë다.,%k gemaakt gehakt vlees van %o,%k zrobiÅ‚@[ao_pl] miÄ™so mielone z %o,%k fez carne moída de %o,%k fez carne picada do %o,,Игрок %k Ñделал отбивную из игрока %o,%k је направио млевено меÑо од %o +%k massacred %o,TXT_OBITUARY13,,,,%o byl@[ao_cs] zmasakrován@[ao_cs] hráÄem %k,%k hat %o niedergemetzelt,,%k masakris %o,%k masacró a %o,,%k verilöylytti %o parkaa,%k a massacré %o,%k lemészárolta %o -t,%k ha fatto di %o carne tritata,%k 㯠%o ã‚’è™æ®ºã—ãŸã€‚,%k ì€(는) %o ì„(를) 참살했다.,%k afgeslacht %o,%k zmasakrowaÅ‚@[ao_pl] %o,%k massacrou %o,,,Игрок %k уÑтроил бойню игроку %o,%k је маÑакрирао %o +%k mutilated %o,TXT_OBITUARY14,,,,%o byl@[ao_cs] zmrzaÄen@[ao_cs] hráÄem %k,%k hat %o verstümmelt,,%k mutilis %o,%k mutiló a %o,,%k silpoi %o paran,%k a mutilé %o,%k megcsonkította %o -t,%k ha massacrato %o,%k 㯠%o ã‚’ãƒãƒ©ãƒãƒ©æ­»ä½“ã«ã—ãŸã€‚,%k ì€(는) %o ì˜ íŒ”ë‹¤ë¦¬ë¥¼ 절단했다.,%k verminkt %o,%k rozszarpaÅ‚@[ao_pl] %o,%k mutilou %o,,,Игрок %k изуродовал игрока %o,%k је мутилирао %o +%k reamed %o,TXT_OBITUARY15,,,,%o byl@[ao_cs] prodÄ›ravÄ›n@[ao_cs] hráÄem %k,%k hat %o aufgerieben,,%k reeldonis %o,%k escarió a %o,,%k porasi %o paran,%k a découpé en fines lamelles %o,%k seggbe rakta %o -t,%k ha squartato %o,%k 㯠%o ã®ç©´ã‚’大ãã広ã’ãŸã€‚,%k ì€(는) %o ì„(를) í¬ê²Œ 혼냈다.,%k geruimd %o,%k rozwierciÅ‚@[ao_pl] %o,%k esquartejou %o,,,Игрок %k проÑверлил игрока %o,%k је наоружао %o +%k ripped %o a new orifice,TXT_OBITUARY16,,,,%o má novou díru od hráÄe %k,%k hat %o eine neue Körperöffnung verpasst,,%k Åiris %o novan orificion,%k le hizo a %o un nuevo orificio,,%k repi %o paralle uuden aukon,%k a ouvert un nouvel orifice a %o,,%k ha aperto a %o un altro orifizio,%k 㯠%o を切り裂ã„ã¦æ–°ã—ã„穴を作ã£ã¦ã‚ã’ãŸã€‚,%k ì€(는) %o ì„(를) 죽여 뜯어서 ìž‘í’ˆì„ ë§Œë“¤ì—ˆë‹¤.,%k gescheurd %o een nieuwe doorlaatopening,%k rozerwaÅ‚@[ao_pl] %o nowy otwór,%k abriu um novo orifício em %o,,,Игрок %k проделал новое отверÑтие в игроке %o,%k је иÑцепао %o нови отвор +%k slaughtered %o,TXT_OBITUARY17,,,,%o byl@[ao_cs] zavraždÄ›n@[ao_cs] hráÄem %k,%k hat %o geschlachtet,,%k buĉis %o,%k sacrificó a %o,,%k teurasti %o paran,%k a meurtri %o,%k lemészárolta %o -t,%k ha macellato %o,%k 㯠%o を屠殺ã—ãŸã€‚,%o ì€(는) %k ì— ì˜í•´ ë„살당했다.,%k geslacht %o,%k zarżn@[irreg_2_pl] %o,%k abateu %o,,,Игрок %k уÑтроил резню игроку %o,%k је заклао %o +%k smashed %o,TXT_OBITUARY18,,,,%o byl@[ao_cs] zmlácen@[ao_cs] hráÄem %k,%k hat %o zerklatscht,,%k frakasis %o,%k destrozó a %o,,%k murskasi %o paran,%k a enfoncé %o,%k földbe döngölte %o -t,%k ha distrutto %o,%k 㯠%o ã‚’ã¶ã£é£›ã°ã—ãŸã€‚,%k ì€(는) %o ì„(를) 내팽개쳤다.,%k gebroken %o,%k stÅ‚ukÅ‚@[ao_pl] %o,%k esmagou %o,,,Игрок %k размазал игрока %o,%k је поломио %o +%k sodomized %o,TXT_OBITUARY19,,,,HrÃ¡Ä %k se dopustil sodomie na hráÄi %o,%k hat %o sodomisiert,,%k sodomizata %o,%k sodomizó a %o,,%k anaaliraiskasi %o paran,%k y a sodomisé n %o,%k szodomizálta %o -t,%k ha sodomizzato %o,%o 㯠%k ã«ã‚«ãƒžã‚’掘られãŸã€‚ ,%o ì€(는) %k ì„(를) 위해 ë“±ì„ ë³´ì˜€ë‹¤.,%k gesodomiseerd %o,%k spenetrowaÅ‚@[ao_pl] %o,%k sodomizou %o,,,Игрок %k Ñодомировал игрока %o,%k је изјебао %o +%k splattered %o,TXT_OBITUARY20,,,,%o byl@[ao_cs] rozplesknut@[ao_cs] hráÄem %k,%k hat %o zerspritzt,,%k disĵetis %o,%k roció a %o,,%k roiski %o paran yltympäri,%k a explosé de %o,%k szétloccsantotta %o -t,%k ha spiaccicato %o,%k 㯠%o ã«ã°ã‚‰æ’’ã‹ã‚ŒãŸã€‚,%k ì€(는) %o ì„(를) 박살냈다.,%k gespat %k gespetterd %o,%k rozbryzgaÅ‚@[ao_pl] %o,%k explodiu %o,,,Игрок %k разбрызгал игрока %o,%k је Ñпљоштио %o +%k squashed %o,TXT_OBITUARY21,,,,%o byl@[ao_cs] rozmáÄknut@[ao_cs] hráÄem %k,%k hat %o zerquetscht,,%k premplatigis %o,%k aplastó a %o,,%k litisti %o paran,%k a écrabouillé %o,%k szétnyomta %o -t mint a csótányt,%k ha schiacciato %o,%k 㯠%o ã«æ½°ã•ã‚ŒãŸã€‚,%k ì€(는) %o ì„(를) 짓ì´ê²¼ë‹¤.,%k geplet %k geplet %o,%k zmiażdżyÅ‚@[ao_pl] %o,%k espatifou %o,,,Игрок %k раÑплющил игрока %o,%k је згњечио %o +%k throttled %o,TXT_OBITUARY22,,,,%o byl@[ao_cs] zaÅ¡krcen@[ao_cs] hráÄem %k,%k hat %o erdrosselt,,%k ekbruligis %o,%k aceleró a %o,,%k polki %o paran,%k a étouffé %o,,%k ha strozzato %o,%k 㯠%o ã«çµžã‚‰ã‚ŒãŸã€‚,%k ì€(는) %o ì„(를) 목 ì¡¸ë¼ ì£½ì˜€ë‹¤.,%k gewurgt %o,"%k udusiÅ‚@[ao_pl] %o +",%k estrangulou %o,,,Игрок %k задушил игрока %o,%k је угушио %o +%k wasted %o,TXT_OBITUARY23,,,,%o byl@[ao_cs] zniÄen@[ao_cs] hráÄem %k,%k hat %o verbraucht,,%k malÅparis %o,%k desechó a %o,,%k kulutti %o paran,%k a décharné %o,,%k ha distrutto %o,%k 㯠%o ã«æ¶ˆã•ã‚ŒãŸã€‚,%k ì€(는) %o ì„(를) 쓰레기처럼 내다 버렸다.,%k verspild %o,%k roztrwoniÅ‚@[ao_pl] %o,%k detonou %o,,,Игрок %k замочил игрока %o,%k је убио %o +%k body bagged %o,TXT_OBITUARY24,,,,HrÃ¡Ä %k narval %o@[psn1_cs] tÄ›lo do pytle,%k hat %o eingesackt,,%k korpo malplenigis %o,%k embolsó a %o,,%k kääri %o paran ruumispussiin,%k a placé %o dans son linceul,,%k ha mandato %o all'obitorio,%k 㯠%o を死体袋ã«ã—ãŸã€‚,%k ì€(는) %o ì˜ ìž¥ë¡€ì‹ì„ 치렀다.,%k lichaam met zakje %o,%k spakowaÅ‚@[ao_pl] %o do torby na zwÅ‚oki,%k mandou %o para o necrotério,,,Игрок %k упаковал игрока %o в мешок Ð´Ð»Ñ Ñ‚Ñ€ÑƒÐ¿Ð¾Ð²,%k је умртвио %o +%k sent %o to Hell,TXT_OBITUARY25,,,,%o byl@[ao_cs] poslán@[ao_cs] do pekla hráÄem %k,%k hat %o zur Hölle fahren lassen,,%k sendis %o al Infero,%k envió a %o al infierno,,%k lähetti %o paran helvettiin,%k a envoyé %o en enfer,,%k ha spedito %o all'Inferno,%k 㯠%o を地ç„ã«é€ã£ãŸã€‚,%o ì€(는) %k ë•ì— 지옥으로 ëŒì•„갔다.,%k verzonden %o naar de hel,%k wysÅ‚aÅ‚@[ao_pl] %o do PiekÅ‚a,%k mandou %o para o Inferno,,,Игрок %k отправил в Ðд игрока %o,%k је поÑлао %o до Врага +%k toasted %o,TXT_OBITUARY26,,,,%o byl@[ao_cs] upeÄen@[ao_cs] hráÄem %k,%k hat %o geröstet,,%k tostita %o,%k tostó a %o,,%k käristi %o paran,%k a grillé %o,%k megpirította %o -t,%k ha arrostito %o,%k 㯠%o を焼å´ã—ãŸã€‚,%o ì€(는) %k ë•ì— 맛있게 구워졌다.,%k geroosterd %o,%k stostowaÅ‚@[ao_pl] %o,%k tostou %o,,,Игрок %k поджарил игрока %o,%k је тоÑтирао %o +%k snuffed %o,TXT_OBITUARY27,,,,%o byl@[ao_cs] rozsápán@[ao_cs] hráÄem %k,%k hat %o vernichtet,,%k snufis %o,%k aspiró a %o,,%k sammutti %o paran,%k a crevé %o,,%k ha spento %o,%k 㯠%o を処刑ã—ãŸã€‚,%o ì€(는) %k ì— ì˜í•´ 짓눌려졌다.,%k gesnuffeld %o,%k powÄ…chaÅ‚@[ao_pl] %o,%k apagou %o,,,Игрок %k прикончил игрока %o,%k је угаÑио %o +%k hosed %o,TXT_OBITUARY28,,,,%o byl@[ao_cs] odstříknut@[ao_cs] hráÄem %k,%k hat %o eingetütet,,%k bagigis %o,%k se cargó a %o,,%k pesi %o paran,%k a arrosé %o,,%k l'ha fatta sopra %o,%k 㯠%o ã«ã¶ã£ã‹ã‘ãŸã€‚,%k ì€(는) %o ì„(를) 패배로 씻겼다.,%k slang %o,%k zaÅ‚atwiÅ‚@[ao_pl] %o,%k metralhou %o,,,Игрок %k раÑÑтрелÑл игрока %o,%k је упÑкао %o +%k sprayed %o,TXT_OBITUARY29,,,,%o byl@[ao_cs] postříkán@[ao_cs] hráÄem %k,%k hat %o pulverisiert,,%k Åprucigis %o,%k pulverizó a %o,,%k ruiskutti %o paran,%k a pulvérise %o,,%k ha vaporizzato %o,%k 㯠%o ã‚’æ’’ã散らã—ãŸã€‚,%o ì˜ í”¼ëŠ” %k ì˜ ë¬¼ê°ìœ¼ë¡œ 쓰였다.,%k gespoten %o,%k rozpryskaÅ‚@[ao_pl] %o,%k pulverizou %o,,,Игрок %k раÑпылил игрока %o,%k је иÑпрÑкао %o +%k made dog meat out of %o,TXT_OBITUARY30,,,,%o byl@[ao_cs] hozen@[ao_cs] psům hráÄem %k,%k hat Hundefutter aus %o gemacht,,%k faris hundan viandon el %o,%k hizo comida para perro de %o,,%k teki %o parasta koiranruokaa,%k a fait de la pâtée pour chien de %o,,%k ha fatto di %o polpette,%k 㯠%o を犬ã®é¤Œã«ã—ãŸã€‚,%k ì€(는) %o ë¡œ ê°œë°¥ì„ ë§Œë“¤ì—ˆë‹¤.,%k gemaakt hondenvlees van %o,%k zrobiÅ‚@[ao_pl] miÄ™so dla psów z %o,%k fez almôndegas de %o,,,Игрок %k Ñкормил пÑам игрока %o,%k је направио пÑеће меÑо од %o +%k beat %o like a cur,TXT_OBITUARY31,,,,%o byl@[ao_cs] zmlácen@[ao_cs] jako pes hráÄem %k,%k hat %o wie einen Hund geschlagen,,%k batis %o kiel kur,%k pateó a %o como a un perro callejero,,%k huitoi %o parkaa kuin rakkia,%k a battu %o,,%k ha battuto %o come un cane,%k 㯠%o を狂犬ã®æ§˜ã«æ‰±ã£ãŸã€‚,%o ì€(는) %k ì—게 똥개처럼 맞았다.,%k beat %o als een hond,%k pobiÅ‚@[ao_pl] %o jak kundla,%k espancou %o como um cachorro,%k espancou %o como um cão,,Игрок %k Ñделал игрока %o как худую Ñвинью,%k је превио %o ко мачку +%k body bagged %o,TXT_OBITUARY32,,,,,,,,,,,,,,,,,,,,,, +%k crushed %o,TXT_OBITUARY33,,,,,,,,,,,,,,,,,,,,,, +%k erased %o,TXT_OBITUARY34,,,,,,,,,,,,,,,,,,,,,, +%k eviscerated %o,TXT_OBITUARY35,,,,,,,,,,,,,,,,,,,,,, +%k flailed %o,TXT_OBITUARY36,,,,,,,,,,,,,,,,,,,,,, +%k hurt %o real bad,TXT_OBITUARY37,,,,,,,,,,,,,,,,,,,,,, +%k manhandled %o,TXT_OBITUARY38,,,,,,,,,,,,,,,,,,,,,, +%k murdered %o,TXT_OBITUARY39,,,,,,,,,,,,,,,,,,,,,, +%k neutered %o,TXT_OBITUARY40,,,,,,,,,,,,,,,,,,,,,, +%k punted %o,TXT_OBITUARY41,,,,,,,,,,,,,,,,,,,,,, +%k shredded %o,TXT_OBITUARY42,,,,,,,,,,,,,,,,,,,,,, +%k slashed %o,TXT_OBITUARY43,,,,,,,,,,,,,,,,,,,,,, +%k sliced %o,TXT_OBITUARY44,,,,,,,,,,,,,,,,,,,,,, +%k smacked %o around,TXT_OBITUARY45,,,,,,,,,,,,,,,,,,,,,, +%k vented %o,TXT_OBITUARY46,,,,,,,,,,,,,,,,,,,,,, +%k ventilated %o,TXT_OBITUARY47,,,,,,,,,,,,,,,,,,,,,, +%k wrecked %o,TXT_OBITUARY48,,,,,,,,,,,,,,,,,,,,,, +%o is excrement,TXT_SELFOBIT1,,,,%o je exkrement,%o wurde zu Exkrement verarbeitet,,%o estas ekskremento,%o es excremento,,%o on ulostetta,%o est une merde,,%o è un escremento,%o ã¯ã‚‚ã¯ã‚„排泄物ã®ã‚ˆã†ã ã€‚,%o ì€(는) ë°°ì„¤ë¬¼ì´ ë˜ì—ˆë‹¤.,%o is uitwerpselen,%o zostaÅ‚@[ao_pl] odpadkami,%o virou escremento,,,%o теперь ÑкÑкремент,%o је Ñада измет +%o is hamburger,TXT_SELFOBIT2,,,,%o je hamburger,%o ist Hamburger,,%o estas hamburgero,%o es una hamburguesa,,%o on hakkelusta,%o est un hamburger,,%o è un hamburger,%o ã¯ãƒãƒ³ãƒãƒ¼ã‚¬ãƒ¼ã«ãªã£ãŸã€‚,%o ì€(는) 고기 ë°˜ì£½ì´ ë˜ì—ˆë‹¤.,%o is hamburger,%o zostaÅ‚@[ao_pl] hamburgerem,%o virou hamburguer,,,%o теперь гамбургер,%o је Ñада пљеÑкавица +%o suffered scrotum separation,TXT_SELFOBIT3,,,,%o prodÄ›lal@[ao_cs] separaci Å¡ourku,%os Eier wurden gebraten,,%o suferis skrotan disigon,%o sufrió separación de escroto,,%o kärsii kivespussin erotuksesta,%o a souffert d'une séparation du scrotum,,%o ha subito la separazione dello scroto,%o ã®é™°åš¢ã¯å‰¥é›¢ã—ã¦ã„ãŸã€‚,%o ì€(는) ê³ ìžê°€ ë˜ì—ˆë‹¤.,%o leed aan scrotumscheiding...,%o doznaÅ‚@[ao_pl] oddzielenia moszny,%o sofreu separação escrotal,,,%o Ñтрадает от потери теÑтикул,%o му је иÑечена патка +%o volunteered for population control,TXT_SELFOBIT4,,,,%o se zůÄastnil@[ao_cs] Äistky obyvatelstva,%o hat sich freiwillig zur Bevölkerungskontrolle gemeldet,,%o volontulis por loÄantarkontrolo,%o fue voluntario para control de población,,%o ilmoittautui vapaaehtoiseksi väestönhallintaan,%o s'est proposé pour un contrôle de la population,,%o si è offerto per il controllo della popolazione,%o ã¯äººå£å‰Šæ¸›æ”¿ç­–ã®å®Ÿé¨“å°ã«å¿—願ã—ãŸã€‚,%o ì€(는) ìžì—°ì— ì˜í•´ 낙태 당했다.,%o vrijwilliger voor bevolkingscontrole,%o zgÅ‚osiÅ‚@[ao_pl] siÄ™ na kontrolÄ™ ludnoÅ›ci,%o se voluntariou para o controle populacional,%o se voluntariou para o controlo populacional,,%o боретÑÑ Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ñелением,%o је волунтирао за контролу популације +%o has suicided,TXT_SELFOBIT5,,,,%o spáchal@[ao_cs] sebevraždu,%o hat Selbstmord begangen,,%o sin mortigis,%o se ha suicidado,,%o on tehnyt itsemurhan,%o s'est suicidé,%o öngyilkos lett,%o si è suicidato,%o ã¯å‹æ‰‹ã«ããŸã°ã£ãŸã€‚,%o ì€(는) 한심하게 ìžì‚´í–ˆë‹¤.,%o heeft zelfmoord gepleegd.,%o popeÅ‚niÅ‚@[ao_pl] samobójstwo,%o se suicidou,%o suicidou-se,,Игрок %o ÑамоубилÑÑ,%o је убио Ñамог Ñебе +%o received the Darwin Award,TXT_SELFOBIT6,,,,%o dostal@[ao_cs] darwinovu cenu,%o hat den Darwinpreis erhalten,,%o ricevis la Darwin-Premion,%o recibió el premio Darwin,,%o sai Darwin-palkinnon,%o a recu la médaille Darwin,És a Darwin Díj nyertese : %o,%o ha ricevuto il Darwin Award,%o ã«ã¯ãƒ€ãƒ¼ã‚¦ã‚£ãƒ³è³žãŒæŽˆä¸Žã•ã‚ŒãŸã€‚,%o ì€(는) 다윈ìƒì„ ë°›ì„ ìžê²©ì´ 있다.,%o ontving de Darwin Award....,%o otrzymaÅ‚@[ao_pl] NagrodÄ™ Darwina,%o ganhou o Prêmio Darwin,,,Игрок %o получил премию Дарвина,%o је добио Дарвиново признање +,,,,,,,,,,,,,,,,,,,,,,, +,Duke Nukem Script quotes,,,,,,,,,,,,,,,,,,,,,, +Auto Aiming,AUTO AIMING,,,,,,,,,,,,,,,,,,,,,, +Show Map: OFF,SHOW MAP: OFF,,,,,,,,,,,,,,,,,,,,,, +Activated,ACTIVATED,,,,,,,,,,,,,,,,,,,,,, +Portable Medkit,PORTABLE MEDKIT,,,,,,,,,,,,,,,,,,,,,, +Locked,LOCKED,,,,,,,,,,,,,,,,,,,,,, +Giving Everything!,GIVING EVERYTHING!,,,,,,,,,,,,,,,,,,,,,, +Boots,BOOTS,,,,,,,,,,,,,,,,,,,,,, +Wasted!,WASTED!,,,,,,,,,,,,,,,,,,,,,, +Unlocked,UNLOCKED,,,,,,,,,,,,,,,,,,,,,, +A Secret Place!,A SECRET PLACE!,,,,,,,,,,,,,,,,,,,,,, +Squish!,SQUISH!,,,,,,,,,,,,,,,,,,,,,, +All Doors Unlocked,ALL DOORS UNLOCKED,,,,,,,,,,,,,,,,,,,,,, +Used Steroids,USED STEROIDS,,,,,,,,,,,,,,,,,,,,,, +Press Space To Restart Level,PRESS SPACE TO RESTART LEVEL,,,,,,,,,,,,,,,,,,,,,, +Ammo For Devastator,AMMO FOR DEVASTATOR,,,,,,,,,,,,,,,,,,,,,, +Deactivated,DEACTIVATED,,,,,,,,,,,,,,,,,,,,,, +Switch Operated Only!,SWITCH OPERATED ONLY!,,,,,,,,,,,,,,,,,,,,,, +God Mode: ON,GOD MODE: ON,,,,,,,,,,,,,,,,,,,,,, +God Mode: OFF,GOD MODE: OFF,,,,,,,,,,,,,,,,,,,,,, +Atomic Health!,ATOMIC HEALTH!,,,,,,,,,,,,,,,,,,,,,, +Crosshair: ON,CROSSHAIR: ON,,,,,,,,,,,,,,,,,,,,,, +Crosshair: OFF,CROSSHAIR: OFF,,,,,,,,,,,,,,,,,,,,,, +You're Too Good To Be Cheating!,YOU'RE TOO GOOD TO BE CHEATING!,,,,,,,,,,,,,,,,,,,,,, +Messages: ON,MESSAGES: ON,,,,,,,,,,,,,,,,,,,,,, +Messages: OFF,MESSAGES: OFF,,,,,,,,,,,,,,,,,,,,,, +Type The Cheat Code:,TYPE THE CHEAT CODE:,,,,,,,,,,,,,,,,,,,,,, +Detail: Low,DETAIL: LOW,,,,,,,,,,,,,,,,,,,,,, +Detail: High,DETAIL: HIGH,,,,,,,,,,,,,,,,,,,,,, +Will Always Have No Future,WILL ALWAYS HAVE NO FUTURE,,,,,,,,,,,,,,,,,,,,,, +Brightness Level: ONe,BRIGHTNESS LEVEL: ONE,,,,,,,,,,,,,,,,,,,,,, +Brightness Level: Two,BRIGHTNESS LEVEL: TWO,,,,,,,,,,,,,,,,,,,,,, +Brightness Level: Three,BRIGHTNESS LEVEL: THREE,,,,,,,,,,,,,,,,,,,,,, +Brightness Level: Four,BRIGHTNESS LEVEL: FOUR,,,,,,,,,,,,,,,,,,,,,, +Brightness Level: Five,BRIGHTNESS LEVEL: FIVE,,,,,,,,,,,,,,,,,,,,,, +Sound: ON,SOUND: ON,,,,,,,,,,,,,,,,,,,,,, +Sound: OFF,SOUND: OFF,,,,,,,,,,,,,,,,,,,,,, +Screen Captured,SCREEN CAPTURED,,,,,,,,,,,,,,,,,,,,,, +Steroids,STEROIDS,,,,,,,,,,,,,,,,,,,,,, +Armor,ARMOR,,,,,,,,,,,,,,,,,,,,,, +Scuba Gear,SCUBA GEAR,,,,,,,,,,,,,,,,,,,,,, +Press F1 For Help,Press F1 for Help,,,,,,,,,,,,,,,,,,,,,, +Jetpack,JETPACK,,,,,,,,,,,,,,,,,,,,,, +Body Suit,BODY SUIT,,,,,,,,,,,,,,,,,,,,,, +Access Card,ACCESS CARD,,,,,,,,,,,,,,,,,,,,,, +Mouse Aiming Off,MOUSE AIMING OFF,,,,,,,,,,,,,,,,,,,,,, +Mouse Aiming On,MOUSE AIMING ON,,,,,,,,,,,,,,,,,,,,,, +Cheat Code: Unrecognized,CHEAT CODE: UNRECOGNIZED,,,,,,,,,,,,,,,,,,,,,, +Holoduke On,HOLODUKE ON,,,,,,,,,,,,,,,,,,,,,, +Holoduke Off,HOLODUKE OFF,,,,,,,,,,,,,,,,,,,,,, +Holoduke Not Found Yet!,HOLODUKE NOT FOUND YET!,,,,,,,,,,,,,,,,,,,,,, +Jetpack Not Found Yet!,JETPACK NOT FOUND YET!,,,,,,,,,,,,,,,,,,,,,, +Holoduke,HOLODUKE,,,,,,,,,,,,,,,,,,,,,, +Jetpack On,JETPACK ON,,,,,,,,,,,,,,,,,,,,,, +Jetpack Off,JETPACK OFF,,,,,,,,,,,,,,,,,,,,,, +Chaingun Cannon!,CHAINGUN CANNON!,,,,,,,,,,,,,,,,,,,,,, +Pipebomb!,PIPEBOMB!,,,,,,,,,,,,,,,,,,,,,, +RPG!,RPG!,,,,,,,,,,,,,,,,,,,,,, +Shotgun,SHOTGUN,,,,,,,,,,,,,,,,,,,,,, +Laser Tripbomb!,LASER TRIPBOMB!,,,,,,,,,,,,,,,,,,,,,, +Freezethrower!,FREEZETHROWER!,,,,,,,,,,,,,,,,,,,,,, +Got Shrinker/Expander!,GOT SHRINKER/EXPANDER!,,,,,,,,,,,,,,,,,,,,,, +Small Medkit: +10,SMALL MEDKIT: +10,,,,,,,,,,,,,,,,,,,,,, +Large Medkit: +30,LARGE MEDKIT: +30,,,,,,,,,,,,,,,,,,,,,, +Ammo For Chaingun Cannon!,AMMO FOR CHAINGUN CANNON!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Rpg!,AMMO FOR RPG!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Pistol!,AMMO FOR PISTOL!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Freezethrower!,AMMO FOR FREEZETHROWER!,,,,,,,,,,,,,,,,,,,,,, +Boots Off,BOOTS OFF,,,,,,,,,,,,,,,,,,,,,, +Boots On,BOOTS ON,,,,,,,,,,,,,,,,,,,,,, +Ammo For Shotgun,AMMO FOR SHOTGUN,,,,,,,,,,,,,,,,,,,,,, +Blue Access Card Required,BLUE ACCESS CARD REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Red Access Card Required,RED ACCESS CARD REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Yellow Access Card Required,YELLOW ACCESS CARD REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Weapon Lowered,WEAPON LOWERED,,,,,,,,,,,,,,,,,,,,,, +Weapon Raised,WEAPON RAISED,,,,,,,,,,,,,,,,,,,,,, +Protective Boots On,PROTECTIVE BOOTS ON,,,,,,,,,,,,,,,,,,,,,, +Scuba Gear On,SCUBA GEAR ON,,,,,,,,,,,,,,,,,,,,,, +Space Suit On,SPACE SUIT ON,,,,,,,,,,,,,,,,,,,,,, +Ammo For Shrinker,AMMO FOR SHRINKER,,,,,,,,,,,,,,,,,,,,,, +Buy Major Stryker,BUY MAJOR STRYKER,,,,,,,,,,,,,,,,,,,,,, +Mighty Foot Engaged,MIGHTY FOOT ENGAGED,,,,,,,,,,,,,,,,,,,,,, +Weapon Mode On,WEAPON MODE ON,,,,,,,,,,,,,,,,,,,,,, +Weapon Mode Off,WEAPON MODE OFF,,,,,,,,,,,,,,,,,,,,,, +Follow Mode Off,FOLLOW MODE OFF,,,,,,,,,,,,,,,,,,,,,, +Follow Mode On,FOLLOW MODE ON,,,,,,,,,,,,,,,,,,,,,, +Run Mode Off,RUN MODE OFF,,,,,Rennen AN,,,,,,,,,,,,,,,,, +Run Mode On,RUN MODE ON,,,,,Rennen AUS,,,,,,,,,,,,,,,,, +Devastator Weapon,DEVASTATOR WEAPON,,,,,,,,,,,,,,,,,,,,,, +Jet Pack,JET PACK,,,,,,,,,,,,,,,,,,,,,, +Airtank,AIRTANK,,,,,,,,,,,,,,,,,,,,,, +Steroids,STEROIDS,,,,,,,,,,,,,,,,,,,,,, +Holoduke,HOLODUKE,,,,,,,,,,,,,,,,,,,,,, +Music: ON,MUSIC: ON,,,,,,,,,,,,,,,,,,,,,, +Music: OFF,MUSIC: OFF,,,,,,,,,,,,,,,,,,,,,, +Scroll Mode: ON,SCROLL MODE: ON,,,,,,,,,,,,,,,,,,,,,, +Scroll Mode: OFF,SCROLL MODE: OFF,,,,,,,,,,,,,,,,,,,,,, +Brightness Level: Six,BRIGHTNESS LEVEL: SIX,,,,,,,,,,,,,,,,,,,,,, +Brightness Level: Seven,BRIGHTNESS LEVEL: SEVEN,,,,,,,,,,,,,,,,,,,,,, +Brightness Level: Eight,BRIGHTNESS LEVEL: EIGHT,,,,,,,,,,,,,,,,,,,,,, +Register Cosmo Today!,REGISTER COSMO TODAY!,,,,,,,,,,,,,,,,,,,,,, +All Locks Toggled,ALL LOCKS TOGGLED,,,,,,,,,,,,,,,,,,,,,, +Night Vision Goggles,NIGHT VISION GOGGLES,,,,,,,,,,,,,,,,,,,,,, +"We're Gonna Fry Your Ass, Nukem!","WE'RE GONNA FRY YOUR ASS, NUKEM!",,,,,,,,,,,,,,,,,,,,,, +Screen Saved,SCREEN SAVED,,,,,,,,,,,,,,,,,,,,,, +Got Used Armor,GOT USED ARMOR,,,,,,,,,,,,,,,,,,,,,, +Pirates Suck!,PIRATES SUCK!,,,,,,,,,,,,,,,,,,,,,, +Night Vision On,NIGHT VISION ON,,,,,,,,,,,,,,,,,,,,,, +Night Vision Off,NIGHT VISION OFF,,,,,,,,,,,,,,,,,,,,,, +You're Burning!,YOU'RE BURNING!,,,,,,,,,,,,,,,,,,,,,, +View Mode Off,VIEW MODE OFF,,,,,,,,,,,,,,,,,,,,,, +View Mode On,VIEW MODE ON,,,,,,,,,,,,,,,,,,,,,, +Show Map: ON,SHOW MAP: ON,,,,,,,,,,,,,,,,,,,,,, +Clipping: ON,CLIPPING: ON,,,,,,,,,,,,,,,,,,,,,, +Clipping: OFF,CLIPPING: OFF,,,,,,,,,,,,,,,,,,,,,, +!!! Incorrect Version !!!,!!! INCORRECT VERSION !!!,,,,,,,,,,,,,,,,,,,,,, +"You Cannot ""Quick Save"" When Dead","YOU CANNOT ""QUICK SAVE"" WHEN DEAD",,,,,,,,,,,,,,,,,,,,,, +Got All Weapons/Ammo,GOT ALL WEAPONS/AMMO,,,,,,,,,,,,,,,,,,,,,, +Got All Inventory,GOT ALL INVENTORY,,,,,,,,,,,,,,,,,,,,,, +Got All Keys,GOT ALL KEYS,,,,,,,,,,,,,,,,,,,,,, +Ammo For Expander,AMMO FOR EXPANDER,,,,,,,,,,,,,,,,,,,,,, +Map Has A Different Number Of Players,MAP HAS A DIFFERENT NUMBER OF PLAYERS,,,,,,,,,,,,,,,,,,,,,, +,Alterations from Duke Caribbean: Life's a Beach,,,,,,,,,,,,,,,,,,,,,, +Crate Of Bananas,CRATE OF BANANAS,,,,,,,,,,,,,,,,,,,,,, +Denied,DENIED,,,,,,,,,,,,,,,,,,,,,, +Sandles,SANDLES,,,,,,,,,,,,,,,,,,,,,, +Approved,APPROVED,,,,,,,,,,,,,,,,,,,,,, +Used Hot Sauce,USED HOT SAUCE,,,,,,,,,,,,,,,,,,,,,, +Ammo For Conchanator,AMMO FOR CONCHANATOR,,,,,,,,,,,,,,,,,,,,,, +Pearl Health!,PEARL HEALTH!,,,,,,,,,,,,,,,,,,,,,, +Hot Sauce,HOT SAUCE,,,,,,,,,,,,,,,,,,,,,, +Suntan Lotion,SUNTAN LOTION,,,,,,,,,,,,,,,,,,,,,, +Snorkle,SNORKLE,,,,,,,,,,,,,,,,,,,,,, +Credit Card,CREDIT CARD,,,,,,,,,,,,,,,,,,,,,, +Triple Poison Shooter!,TRIPLE POISON SHOOTER!,,,,,,,,,,,,,,,,,,,,,, +Pineapple!,PINEAPPLE!,,,,,,,,,,,,,,,,,,,,,, +Coconut Launcher!,COCONUT LAUNCHER!,,,,,,,,,,,,,,,,,,,,,, +Super Soak'em!,SUPER SOAK'EM!,,,,,,,,,,,,,,,,,,,,,, +Voodoo Trip Bomb!,VOODOO TRIP BOMB!,,,,,,,,,,,,,,,,,,,,,, +Ice Crusher!,ICE CRUSHER!,,,,,,,,,,,,,,,,,,,,,, +Voodoo Ring!,VOODOO RING!,,,,,,,,,,,,,,,,,,,,,, +Single Banana: +10,SINGLE BANANA: +10,,,,,,,,,,,,,,,,,,,,,, +Bunch Of Bananas: +30,BUNCH OF BANANAS: +30,,,,,,,,,,,,,,,,,,,,,, +Ammo For Triple Poison Shooter!,AMMO FOR TRIPLE POISON SHOOTER!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Coconut Launcher!,AMMO FOR COCONUT LAUNCHER!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Water Pistol!,AMMO FOR WATER PISTOL!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Ice Crusher!,AMMO FOR ICE CRUSHER!,,,,,,,,,,,,,,,,,,,,,, +Sandles Off,SANDLES OFF,,,,,,,,,,,,,,,,,,,,,, +Sandles On,SANDLES ON,,,,,,,,,,,,,,,,,,,,,, +Ammo For Super Soak'em!,AMMO FOR SUPER SOAK'EM!,,,,,,,,,,,,,,,,,,,,,, +Blue Credit Card Required,BLUE CREDIT CARD REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Red Credit Card Required,RED CREDIT CARD REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Yellow Credit Card Required,YELLOW CREDIT CARD REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Protective Sandles On,PROTECTIVE SANDLES ON,,,,,,,,,,,,,,,,,,,,,, +Snorkle On,SNORKLE ON,,,,,,,,,,,,,,,,,,,,,, +Ammo For Voodoo Ring!,AMMO FOR VOODOO RING!,,,,,,,,,,,,,,,,,,,,,, +Conchanator Weapon,CONCHANATOR WEAPON,,,,,,,,,,,,,,,,,,,,,, +Hot Sauce,HOT SAUCE,,,,,,,,,,,,,,,,,,,,,, +Sunglasses,SUNGLASSES,,,,,,,,,,,,,,,,,,,,,, +This Party Is Over Nukem,THIS PARTY IS OVER NUKEM,,,,,,,,,,,,,,,,,,,,,, +Got Used Suntan Lotion,GOT USED SUNTAN LOTION,,,,,,,,,,,,,,,,,,,,,, +Sunglasses On,SUNGLASSES ON,,,,,,,,,,,,,,,,,,,,,, +Sunglasses Off,SUNGLASSES OFF,,,,,,,,,,,,,,,,,,,,,, +,"Episodes, Skills, Maps",,,,,,,,,,,,,,,,,,,,,, +L.A. Meltdown,L.A. MELTDOWN,,,,,,,,,,,,,,,,,,,,,, +Lunar Apocalypse,LUNAR APOCALYPSE,,,,,,,,,,,,,,,,,,,,,, +Shrapnel City,SHRAPNEL CITY,,,,,,,,,,,,,,,,,,,,,, +The Birth,THE BIRTH,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Piece Of Cake,PIECE OF CAKE,,,,,,,,,,,,,,,,,,,,,, +Let's Rock,LET'S ROCK,,,,,,,,,,,,,,,,,,,,,, +Come Get Some,COME GET SOME,,,,,,,,,,,,,,,,,,,,,, +Damn I'm Good,DAMN I'M GOOD,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Hollywood Holocaust,HOLLYWOOD HOLOCAUST,,,,,,,,,,,,,,,,,,,,,, +Red Light District,RED LIGHT DISTRICT,,,,,,,,,,,,,,,,,,,,,, +Death Row,DEATH ROW,,,,,,,,,,,,,,,,,,,,,, +Toxic Dump,TOXIC DUMP,,,,,,,,,,,,,,,,,,,,,, +The Abyss,THE ABYSS,,,,,,,,,,,,,,,,,,,,,, +Launch Facility,LAUNCH FACILITY,,,,,,,,,,,,,,,,,,,,,, +Faces Of Death,FACES OF DEATH,,,,,,,,,,,,,,,,,,,,,, +User Map,USER MAP,,,,,,,,,,,,,,,,,,,,,, +Void Zone,VOID ZONE,,,,,,,,,,,,,,,,,,,,,, +Roach Condo,ROACH CONDO,,,,,,,,,,,,,,,,,,,,,, +Antiprofit,ANTIPROFIT,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Spaceport,SPACEPORT,,,,,,,,,,,,,,,,,,,,,, +Incubator,INCUBATOR,,,,,,,,,,,,,,,,,,,,,, +Warp Factor,WARP FACTOR,,,,,,,,,,,,,,,,,,,,,, +Fusion Station,FUSION STATION,,,,,,,,,,,,,,,,,,,,,, +Occupied Territory,OCCUPIED TERRITORY,,,,,,,,,,,,,,,,,,,,,, +Tiberius Station,TIBERIUS STATION,,,,,,,,,,,,,,,,,,,,,, +Lunar Reactor,LUNAR REACTOR,,,,,,,,,,,,,,,,,,,,,, +Dark Side,DARK SIDE,,,,,,,,,,,,,,,,,,,,,, +Overlord,OVERLORD,,,,,,,,,,,,,,,,,,,,,, +Spin Cycle,SPIN CYCLE,,,,,,,,,,,,,,,,,,,,,, +Lunatic Fringe,LUNATIC FRINGE,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Raw Meat,RAW MEAT,,,,,,,,,,,,,,,,,,,,,, +Bank Roll,BANK ROLL,,,,,,,,,,,,,,,,,,,,,, +Flood Zone,FLOOD ZONE,,,,,,,,,,,,,,,,,,,,,, +L.A. Rumble,L.A. RUMBLE,,,,,,,,,,,,,,,,,,,,,, +Movie Set,MOVIE SET,,,,,,,,,,,,,,,,,,,,,, +Rabid Transit,RABID TRANSIT,,,,,,,,,,,,,,,,,,,,,, +Fahrenheit,FAHRENHEIT,,,,,,,,,,,,,,,,,,,,,, +Hotel Hell,HOTEL HELL,,,,,,,,,,,,,,,,,,,,,, +Stadium,STADIUM,,,,,,,,,,,,,,,,,,,,,, +Tier Drops,TIER DROPS,,,,,,,,,,,,,,,,,,,,,, +Freeway,FREEWAY,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +It's Impossible,IT'S IMPOSSIBLE,,,,,,,,,,,,,,,,,,,,,, +Duke-Burger,DUKE-BURGER,,,,,,,,,,,,,,,,,,,,,, +Shop-N-Bag,SHOP-N-BAG,,,,,,,,,,,,,,,,,,,,,, +Babe Land,BABE LAND,,,,,,,,,,,,,,,,,,,,,, +Pigsty,PIGSTY,,,,,,,,,,,,,,,,,,,,,, +Going Postal,GOING POSTAL,,,,,,,,,,,,,,,,,,,,,, +Xxx-Stacy,XXX-STACY,,,,,,,,,,,,,,,,,,,,,, +Critical Mass,CRITICAL MASS,,,,,,,,,,,,,,,,,,,,,, +Derelict,DERELICT,,,,,,,,,,,,,,,,,,,,,, +The Queen,THE QUEEN,,,,,,,,,,,,,,,,,,,,,, +Area 51,AREA 51,,,,,,,,,,,,,,,,,,,,,, +,Duke Caribbean,,,,,,,,,,,,,,,,,,,,,, +Vacation Dukematch,VACATION DUKEMATCH,,,,,,,,,,,,,,,,,,,,,, +Life's A Beach,LIFE'S A BEACH,,,,,,,,,,,,,,,,,,,,,, +Low Tide,LOW TIDE,,,,,,,,,,,,,,,,,,,,,, +Makin' Waves,MAKIN' WAVES,,,,,,,,,,,,,,,,,,,,,, +Big Kahuna,BIG KAHUNA,,,,,,,,,,,,,,,,,,,,,, +Tsunami,TSUNAMI,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Island Hopping,ISLAND HOPPING,,,,,,,,,,,,,,,,,,,,,, +Hidden Grotto,HIDDEN GROTTO,,,,,,,,,,,,,,,,,,,,,, +Cruise Ship,CRUISE SHIP,,,,,,,,,,,,,,,,,,,,,, +The Docks,THE DOCKS,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Caribbean Catastrophe,CARIBBEAN CATASTROPHE,,,,,,,,,,,,,,,,,,,,,, +Market Melee,MARKET MELEE,,,,,,,,,,,,,,,,,,,,,, +Mr. Splashy's,MR. SPLASHY'S,,,,,,,,,,,,,,,,,,,,,, +The Wavemistress,THE WAVEMISTRESS,,,,,,,,,,,,,,,,,,,,,, +Lost Lagoon,LOST LAGOON,,,,,,,,,,,,,,,,,,,,,, +Voodoo Caves,VOODOO CAVES,,,,,,,,,,,,,,,,,,,,,, +The Alien Remains,THE ALIEN REMAINS,,,,,,,,,,,,,,,,,,,,,, +A Full House,A FULL HOUSE,,,,,,,,,,,,,,,,,,,,,, +,DukeDC,,,,,,,,,,,,,,,,,,,,,, +Duke It Out In D.C.,DUKE IT OUT IN D.C.,,,,,,,,,,,,,,,,,,,,,, +Hell To The Chief,HELL TO THE CHIEF,,,,,,,,,,,,,,,,,,,,,, +Memorial Service,MEMORIAL SERVICE,,,,,,,,,,,,,,,,,,,,,, +Nuked Files,NUKED FILES,,,,,,,,,,,,,,,,,,,,,, +Smithsonian Terror,SMITHSONIAN TERROR,,,,,,,,,,,,,,,,,,,,,, +Capitol Punishment,CAPITOL PUNISHMENT,,,,,,,,,,,,,,,,,,,,,, +Metro Mayhem,METRO MAYHEM,,,,,,,,,,,,,,,,,,,,,, +Brown Water,BROWN WATER,,,,,,,,,,,,,,,,,,,,,, +Dread October,DREAD OCTOBER,,,,,,,,,,,,,,,,,,,,,, +Nuke Proof,NUKE PROOF,,,,,,,,,,,,,,,,,,,,,, +Top Secret,TOP SECRET,,,,,,,,,,,,,,,,,,,,,, +,Nuclear Winter,,,,,,,,,,,,,,,,,,,,,, +Nuclear Winter,NUCLEAR WINTER,,,,,,,,,,,,,,,,,,,,,, +Deja Vu,DEJA VU,,,,,,,,,,,,,,,,,,,,,, +Where It All Began,WHERE IT ALL BEGAN,,,,,,,,,,,,,,,,,,,,,, +Land Of Forgotten Toys,LAND OF FORGOTTEN TOYS,,,,,,,,,,,,,,,,,,,,,, +Santa's Corporate Hq,SANTA'S CORPORATE HQ,,,,,,,,,,,,,,,,,,,,,, +The Backdoor,THE BACKDOOR,,,,,,,,,,,,,,,,,,,,,, +Christmas Village,CHRISTMAS VILLAGE,,,,,,,,,,,,,,,,,,,,,, +Here Comes Santa Claws,HERE COMES SANTA CLAWS,,,,,,,,,,,,,,,,,,,,,, +Santamatch,SANTAMATCH,,,,,,,,,,,,,,,,,,,,,, +,NAM,,,,,,,,,,,,,,,,,,,,,, +Inventory Item,INVENTORY ITEM,,,,,,,,,,,,,,,,,,,,,, +All Ammo Crates Found...Get Back To The M113,ALL AMMO CRATES FOUND...GET BACK TO THE M113,,,,,,,,,,,,,,,,,,,,,, +Tank Mode On,TANK MODE ON,,,,,,,,,,,,,,,,,,,,,, +Killed In Action...Press Space To Restart Level,KILLED IN ACTION...PRESS SPACE TO RESTART LEVEL,,,,,,,,,,,,,,,,,,,,,, +You Need Ammo To Use This Weapon,YOU NEED AMMO TO USE THIS WEAPON,,,,,,,,,,,,,,,,,,,,,, +M-16 Rifle!,M-16 RIFLE!,,,,,,,,,,,,,,,,,,,,,, +Tank,TANK,,,,,,,,,,,,,,,,,,,,,, +Armor Vest,ARMOR VEST,,,,,,,,,,,,,,,,,,,,,, +Chemical Mine!,CHEMICAL MINE!,,,,,,,,,,,,,,,,,,,,,, +Huey,HUEY,,,,,,,,,,,,,,,,,,,,,, +Mine Placed,MINE PLACED,,,,,,,,,,,,,,,,,,,,,, +Holosoldier On,HOLOSOLDIER ON,,,,,,,,,,,,,,,,,,,,,, +Holosoldier Off,HOLOSOLDIER OFF,,,,,,,,,,,,,,,,,,,,,, +Holosoldier Not Found Yet!,HOLOSOLDIER NOT FOUND YET!,,,,,,,,,,,,,,,,,,,,,, +Huey Not Found Yet!,HUEY NOT FOUND YET!,,,,,,,,,,,,,,,,,,,,,, +Holosoldier,HOLOSOLDIER,,,,,,,,,,,,,,,,,,,,,, +Huey Mode On,HUEY MODE ON,,,,,,,,,,,,,,,,,,,,,, +Huey Mode Off,HUEY MODE OFF,,,,,,,,,,,,,,,,,,,,,, +M-60 Machine Gun!,M-60 MACHINE GUN!,,,,,,,,,,,,,,,,,,,,,, +Grenade!,GRENADE!,,,,,,,,,,,,,,,,,,,,,, +M-72 Law!,M-72 LAW!,,,,,,,,,,,,,,,,,,,,,, +Claymore Mine!,CLAYMORE MINE!,,,,,,,,,,,,,,,,,,,,,, +Flamethrower !,FLAMETHROWER !,,,,,,,,,,,,,,,,,,,,,, +M-79 Grenade Launcher!,M-79 GRENADE LAUNCHER!,,,,,,,,,,,,,,,,,,,,,, +Reloading Rocket Launcher,RELOADING ROCKET LAUNCHER,,,,,,,,,,,,,,,,,,,,,, +Medikit: +30,MEDIKIT: +30,,,,,,,,,,,,,,,,,,,,,, +Ammo For M-60!,AMMO FOR M-60!,,,,,,,,,,,,,,,,,,,,,, +Radioman - Calling In Fire Mission (High Explosive),RADIOMAN - CALLING IN FIRE MISSION (HIGH EXPLOSIVE),,,,,,,,,,,,,,,,,,,,,, +Ammo For M-16!,AMMO FOR M-16!,,,,,,,,,,,,,,,,,,,,,, +Rocket Launcher,ROCKET LAUNCHER,,,,,,,,,,,,,,,,,,,,,, +Ammo For Shotgun!,AMMO FOR SHOTGUN!,,,,,,,,,,,,,,,,,,,,,, +Defense System Malfunction,DEFENSE SYSTEM MALFUNCTION,,,,,,,,,,,,,,,,,,,,,, +Empty,EMPTY,,,,,,,,,,,,,,,,,,,,,, +You Can't Use Tank And Huey At The Same Time !!!,YOU CAN'T USE TANK AND HUEY AT THE SAME TIME !!!,,,,,,,,,,,,,,,,,,,,,, +Flare Ready,FLARE READY,,,,,,,,,,,,,,,,,,,,,, +Knife,KNIFE,,,,,,,,,,,,,,,,,,,,,, +Huey,HUEY,,,,,,,,,,,,,,,,,,,,,, +Ctf,CTF,,,,,,,,,,,,,,,,,,,,,, +Tank,TANK,,,,,,,,,,,,,,,,,,,,,, +Holosoldier,HOLOSOLDIER,,,,,,,,,,,,,,,,,,,,,, +Radioman - Following,RADIOMAN - FOLLOWING,,,,,,,,,,,,,,,,,,,,,, +Mine Disarmed,MINE DISARMED,,,,,,,,,,,,,,,,,,,,,, +Mine Ready,MINE READY,,,,,,,,,,,,,,,,,,,,,, +Trip Flare Placed,TRIP FLARE PLACED,,,,,,,,,,,,,,,,,,,,,, +Radioman - Can't Call In Fire Mission,RADIOMAN - CAN'T CALL IN FIRE MISSION,,,,,,,,,,,,,,,,,,,,,, +Medic - Following,MEDIC - FOLLOWING,,,,,,,,,,,,,,,,,,,,,, +Medic - Awaiting Further Orders,MEDIC - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Demoman - Following,DEMOMAN - FOLLOWING,,,,,,,,,,,,,,,,,,,,,, +Demoman - Awaiting Further Orders,DEMOMAN - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Demoman - Placing Apers Mine,DEMOMAN - PLACING APERS MINE,,,,,,,,,,,,,,,,,,,,,, +Demoman - Placing C-4 Explosive,DEMOMAN - PLACING C-4 EXPLOSIVE,,,,,,,,,,,,,,,,,,,,,, +Grunt - Following,GRUNT - FOLLOWING,,,,,,,,,,,,,,,,,,,,,, +Grunt - Awaiting Further Orders,GRUNT - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Grunt - M-16 Ambush Mode,GRUNT - M-16 AMBUSH MODE,,,,,,,,,,,,,,,,,,,,,, +Radioman - Awaiting Further Orders,RADIOMAN - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Grunt - M 72 Ambush Mode,GRUNT - M 72 AMBUSH MODE,,,,,,,,,,,,,,,,,,,,,, +Laser Loading,LASER LOADING,,,,,,,,,,,,,,,,,,,,,, +Laser Ready,LASER READY,,,,,,,,,,,,,,,,,,,,,, +You Are On The Blue Team,YOU ARE ON THE BLUE TEAM,,,,,,,,,,,,,,,,,,,,,, +You Are On The Red Team,YOU ARE ON THE RED TEAM,,,,,,,,,,,,,,,,,,,,,, +You Got The Enemy Flag...Take It Back To Your Banner,YOU GOT THE ENEMY FLAG...TAKE IT BACK TO YOUR BANNER,,,,,,,,,,,,,,,,,,,,,, +You Got The Beast Flag,YOU GOT THE BEAST FLAG,,,,,,,,,,,,,,,,,,,,,, +Crawl And Press Space To Activate Beast Mode,CRAWL AND PRESS SPACE TO ACTIVATE BEAST MODE,,,,,,,,,,,,,,,,,,,,,, +Blue Team Wins,BLUE TEAM WINS,,,,,,,,,,,,,,,,,,,,,, +Red Team Wins,RED TEAM WINS,,,,,,,,,,,,,,,,,,,,,, +Apers Mine ( 5),APERS MINE ( 5),,,,,,,,,,,,,,,,,,,,,, +Trip Flare ( 5),TRIP FLARE ( 5),,,,,,,,,,,,,,,,,,,,,, +C-4 Explosive,C-4 EXPLOSIVE,,,,,,,,,,,,,,,,,,,,,, +C-4 Placed,C-4 PLACED,,,,,,,,,,,,,,,,,,,,,, +Press Space To View Map,PRESS SPACE TO VIEW MAP,,,,,,,,,,,,,,,,,,,,,, +Booby Trap !!!,BOOBY TRAP !!!,,,,,,,,,,,,,,,,,,,,,, +Mine Detector,MINE DETECTOR,,,,,,,,,,,,,,,,,,,,,, +Radioman - Calling In Fire Mission (Smoke),RADIOMAN - CALLING IN FIRE MISSION (SMOKE),,,,,,,,,,,,,,,,,,,,,, +Ammo For M2machine Gun!,AMMO FOR M2MACHINE GUN!,,,,,,,,,,,,,,,,,,,,,, +M2machine Gun [Press Space To Fire],M2MACHINE GUN [PRESS SPACE TO FIRE],,,,,,,,,,,,,,,,,,,,,, +You're Bleeding,YOU'RE BLEEDING,,,,,,,,,,,,,,,,,,,,,, +A-Gunner,A-GUNNER,,,,,,,,,,,,,,,,,,,,,, +Machine Gunner,MACHINE GUNNER,,,,,,,,,,,,,,,,,,,,,, +Sniper,SNIPER,,,,,,,,,,,,,,,,,,,,,, +Grenadier,GRENADIER,,,,,,,,,,,,,,,,,,,,,, +Point Man,POINT MAN,,,,,,,,,,,,,,,,,,,,,, +Medic,MEDIC,,,,,,,,,,,,,,,,,,,,,, +Squad Leader,SQUAD LEADER,,,,,,,,,,,,,,,,,,,,,, +Killed In Action,KILLED IN ACTION,,,,,,,,,,,,,,,,,,,,,, +Booby Trap Disarmed,BOOBY TRAP DISARMED,,,,,,,,,,,,,,,,,,,,,, +M-60 Machine Gun [Press Space To Fire],M-60 MACHINE GUN [PRESS SPACE TO FIRE],,,,,,,,,,,,,,,,,,,,,, +[Drop Ammo],[DROP AMMO],,,,,,,,,,,,,,,,,,,,,, +[C-4],[C-4],,,,,,,,,,,,,,,,,,,,,, +[Flare],[FLARE],,,,,,,,,,,,,,,,,,,,,, +[Heal],[HEAL],,,,,,,,,,,,,,,,,,,,,, +[Fire Mission],[FIRE MISSION],,,,,,,,,,,,,,,,,,,,,, +[More Ammo],[MORE AMMO],,,,,,,,,,,,,,,,,,,,,, +Medical Supplies,MEDICAL SUPPLIES,,,,,,,,,,,,,,,,,,,,,, +Viet Cong Ammunition,VIET CONG AMMUNITION,,,,,,,,,,,,,,,,,,,,,, +Rotten Food,ROTTEN FOOD,,,,,,,,,,,,,,,,,,,,,, +Sniper Rifle!,SNIPER RIFLE!,,,,,,,,,,,,,,,,,,,,,, +60mm Mortar,60MM MORTAR,,,,,,,,,,,,,,,,,,,,,, +Ammo For 60mm Mortar!,AMMO FOR 60MM MORTAR!,,,,,,,,,,,,,,,,,,,,,, +Shortest [ 1] 2 3 4 5 6 7 Longest,SHORTEST [ 1] 2 3 4 5 6 7 LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest 1 [ 2] 3 4 5 6 7 Longest,SHORTEST 1 [ 2] 3 4 5 6 7 LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest 1 2 [ 3] 4 5 6 7 Longest,SHORTEST 1 2 [ 3] 4 5 6 7 LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest 1 2 3 [ 4] 5 6 7 Longest,SHORTEST 1 2 3 [ 4] 5 6 7 LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest 1 2 3 4 [ 5] 6 7 Longest,SHORTEST 1 2 3 4 [ 5] 6 7 LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest 1 2 3 4 5 [ 6] 7 Longest,SHORTEST 1 2 3 4 5 [ 6] 7 LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest 1 2 3 4 5 6 [ 7] Longest,SHORTEST 1 2 3 4 5 6 [ 7] LONGEST,,,,,,,,,,,,,,,,,,,,,, +Rifleman,RIFLEMAN,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Tour Of Duty I,TOUR OF DUTY I,,,,,,,,,,,,,,,,,,,,,, +Tour Of Duty Ii,TOUR OF DUTY II,,,,,,,,,,,,,,,,,,,,,, +Multiplayer I,MULTIPLAYER I,,,,,,,,,,,,,,,,,,,,,, +Multiplayer Ii,MULTIPLAYER II,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Boot,BOOT,,,,,,,,,,,,,,,,,,,,,, +Grunt,GRUNT,,,,,,,,,,,,,,,,,,,,,, +Salty,SALTY,,,,,,,,,,,,,,,,,,,,,, +Locked On,LOCKED ON,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Base Camp,BASE CAMP,,,,,,,,,,,,,,,,,,,,,, +Assault,ASSAULT,,,,,,,,,,,,,,,,,,,,,, +Hill 104,HILL 104,,,,,,,,,,,,,,,,,,,,,, +Contact Lost,CONTACT LOST,,,,,,,,,,,,,,,,,,,,,, +Huey Down,HUEY DOWN,,,,,,,,,,,,,,,,,,,,,, +Search And Destroy,SEARCH AND DESTROY,,,,,,,,,,,,,,,,,,,,,, +Pow Camp,POW CAMP,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Good Morning,GOOD MORNING,,,,,,,,,,,,,,,,,,,,,, +Village Sweep,VILLAGE SWEEP,,,,,,,,,,,,,,,,,,,,,, +Night Hunters,NIGHT HUNTERS,,,,,,,,,,,,,,,,,,,,,, +Payback Time,PAYBACK TIME,,,,,,,,,,,,,,,,,,,,,, +Casual Ties,CASUAL TIES,,,,,,,,,,,,,,,,,,,,,, +Bloody River,BLOODY RIVER,,,,,,,,,,,,,,,,,,,,,, +Platoonium,PLATOONIUM,,,,,,,,,,,,,,,,,,,,,, +Showdown In Saigon,SHOWDOWN IN SAIGON,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Beirut [Ctf],BEIRUT [CTF],,,,,,,,,,,,,,,,,,,,,, +Defend [Ctf],DEFEND [CTF],,,,,,,,,,,,,,,,,,,,,, +Jungle [Ctf],JUNGLE [CTF],,,,,,,,,,,,,,,,,,,,,, +Mortar Combat [Ctf],MORTAR COMBAT [CTF],,,,,,,,,,,,,,,,,,,,,, +Shack [Ctf],SHACK [CTF],,,,,,,,,,,,,,,,,,,,,, +Town [Ctf],TOWN [CTF],,,,,,,,,,,,,,,,,,,,,, +Casual Ties [Fireteam],CASUAL TIES [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +Night Hunters [Fireteam],NIGHT HUNTERS [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +Assault [Fireteam],ASSAULT [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +Contact Lost [Fireteam],CONTACT LOST [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +Search And Destroy [Fireteam],SEARCH AND DESTROY [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Beirut [Gm],BEIRUT [GM],,,,,,,,,,,,,,,,,,,,,, +Chemical Factory [Gm],CHEMICAL FACTORY [GM],,,,,,,,,,,,,,,,,,,,,, +Command Post [Gm],COMMAND POST [GM],,,,,,,,,,,,,,,,,,,,,, +Dang Street [Gm],DANG STREET [GM],,,,,,,,,,,,,,,,,,,,,, +Desert Storm [Gm],DESERT STORM [GM],,,,,,,,,,,,,,,,,,,,,, +Guerrilla Warfare [Gm],GUERRILLA WARFARE [GM],,,,,,,,,,,,,,,,,,,,,, +Mall-Ice [Gm],MALL-ICE [GM],,,,,,,,,,,,,,,,,,,,,, +Middle East [Gm],MIDDLE EAST [GM],,,,,,,,,,,,,,,,,,,,,, +,WW2GI,,,,,,,,,,,,,,,,,,,,,, +Medikit,MEDIKIT,,,,,,,,,,,,,,,,,,,,,, +Explosives,EXPLOSIVES,,,,,,,,,,,,,,,,,,,,,, +Locked,LOCKED,,,,,,,,,,,,,,,,,,,,,, +Killed In Action...Press Open To Restart Level,KILLED IN ACTION...PRESS OPEN TO RESTART LEVEL,,,,,,,,,,,,,,,,,,,,,, +You Need 60mm Shells To Use Mortar,YOU NEED 60mm SHELLS TO USE MORTAR,,,,,,,,,,,,,,,,,,,,,, +M1 Thompson!,M1 THOMPSON!,,,,,,,,,,,,,,,,,,,,,, +Small Medikit,SMALL MEDIKIT,,,,,,,,,,,,,,,,,,,,,, +Chemical Mine!,CHEMICAL MINE!,,,,,,,,,,,,,,,,,,,,,, +Mine Placed,MINE PLACED,,,,,,,,,,,,,,,,,,,,,, +Disarming...,DISARMING...,,,,,,,,,,,,,,,,,,,,,, +Ordering Fire Mission,ORDERING FIRE MISSION,,,,,,,,,,,,,,,,,,,,,, +Fire Mission Cancelled,FIRE MISSION CANCELLED,,,,,,,,,,,,,,,,,,,,,, +All 88'S Aren't Destroyed Yet !!!,ALL 88'S AREN'T DESTROYED YET !!!,,,,,,,,,,,,,,,,,,,,,, +Browning Automatic Rifle!,BROWNING AUTOMATIC RIFLE!,,,,,,,,,,,,,,,,,,,,,, +Grenade!,GRENADE!,,,,,,,,,,,,,,,,,,,,,, +Bazooka!,BAZOOKA!,,,,,,,,,,,,,,,,,,,,,, +Mp40!,MP40!,,,,,,,,,,,,,,,,,,,,,, +Tnt!,TNT!,,,,,,,,,,,,,,,,,,,,,, +Flamethrower!,FLAMETHROWER!,,,,,,,,,,,,,,,,,,,,,, +Grenade Garand!,GRENADE GARAND!,,,,,,,,,,,,,,,,,,,,,, +Reloading Rocket Launcher,RELOADING ROCKET LAUNCHER,,,,,,,,,,,,,,,,,,,,,, +Small Medikit,SMALL MEDIKIT,,,,,,,,,,,,,,,,,,,,,, +Ammo For Browning Automatic Rifle!,AMMO FOR BROWNING AUTOMATIC RIFLE!,,,,,,,,,,,,,,,,,,,,,, +Radioman - Calling In Fire Mission (High Explosive),RADIOMAN - CALLING IN FIRE MISSION (HIGH EXPLOSIVE),,,,,,,,,,,,,,,,,,,,,, +Ammo For M1 Thompson!,AMMO FOR M1 THOMPSON!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Colt 1911!,AMMO FOR COLT 1911!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Sniper Rifle!,AMMO FOR SNIPER RIFLE!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Mp40!,AMMO FOR MP40!,,,,,,,,,,,,,,,,,,,,,, +Colt 1911!,COLT 1911!,,,,,,,,,,,,,,,,,,,,,, +Private Mccurkee Dead,PRIVATE MCCURKEE DEAD,,,,,,,,,,,,,,,,,,,,,, +Defense System Malfunction,DEFENSE SYSTEM MALFUNCTION,,,,,,,,,,,,,,,,,,,,,, +Bazooka Shells,BAZOOKA SHELLS,,,,,,,,,,,,,,,,,,,,,, +Out Of Mortar Shells,OUT OF MORTAR SHELLS,,,,,,,,,,,,,,,,,,,,,, +Knife,KNIFE,,,,,,,,,,,,,,,,,,,,,, +60mm Shells For Mortar,60MM SHELLS FOR MORTAR,,,,,,,,,,,,,,,,,,,,,, +Mines,MINES,,,,,,,,,,,,,,,,,,,,,, +Smokes!,SMOKES!,,,,,,,,,,,,,,,,,,,,,, +Mine Detector,MINE DETECTOR,,,,,,,,,,,,,,,,,,,,,, +Mad Cow Mode Activated,MAD COW MODE ACTIVATED,,,,,,,,,,,,,,,,,,,,,, +All Locks Toggled,ALL LOCKS TOGGLED,,,,,,,,,,,,,,,,,,,,,, +Cigarettes,CIGARETTES,,,,,,,,,,,,,,,,,,,,,, +Mine Disarmed,MINE DISARMED,,,,,,,,,,,,,,,,,,,,,, +Screen Saved,SCREEN SAVED,,,,,,,,,,,,,,,,,,,,,, +Activate 60mm Shells To Use Mortar,ACTIVATE 60mm SHELLS TO USE MORTAR,,,,,,,,,,,,,,,,,,,,,, +Mine Ready,MINE READY,,,,,,,,,,,,,,,,,,,,,, +You Smoke Some Cigarettes,YOU SMOKE SOME CIGARETTES,,,,,,,,,,,,,,,,,,,,,, +Proceed Into Village,PROCEED INTO VILLAGE,,,,,,,,,,,,,,,,,,,,,, +Private Mccurkee - Following,PRIVATE McCURKEE - FOLLOWING,,,,,,,,,,,,,,,,,,,,,, +Private Mccurkee Dead,PRIVATE McCURKEE DEAD,,,,,,,,,,,,,,,,,,,,,, +Private Mccurkee - Awaiting Further Orders,PRIVATE McCURKEE - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Cannot Load Multiplayer Game,CANNOT LOAD MULTIPLAYER GAME,,,,,,,,,,,,,,,,,,,,,, +Radioman - Can't Call In Fire Mission,RADIOMAN - CAN'T CALL IN FIRE MISSION,,,,,,,,,,,,,,,,,,,,,, +Medic - Following,MEDIC - FOLLOWING,,,,,,,,,,,,,,,,,,,,,, +Medic - Awaiting Further Orders,MEDIC - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Demoman - Following,DEMOMAN - FOLLOWING,,,,,,,,,,,,,,,,,,,,,, +Demoman - Awaiting Further Orders,DEMOMAN - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Demoman - Placing A Mine,DEMOMAN - PLACING A MINE,,,,,,,,,,,,,,,,,,,,,, +Demoman - Placing Explosives,DEMOMAN - PLACING EXPLOSIVES,,,,,,,,,,,,,,,,,,,,,, +Grunt - Following,GRUNT - FOLLOWING,,,,,,,,,,,,,,,,,,,,,, +Grunt - Awaiting Further Orders,GRUNT - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Grunt - M-16 Ambush Mode,GRUNT - M-16 AMBUSH MODE,,,,,,,,,,,,,,,,,,,,,, +Radioman - Awaiting Further Orders,RADIOMAN - AWAITING FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Can't Go Further Or You'll Drown,CAN'T GO FURTHER OR YOU'LL DROWN,,,,,,,,,,,,,,,,,,,,,, +Booze!,BOOZE!,,,,,,,,,,,,,,,,,,,,,, +Laser Loading,LASER LOADING,,,,,,,,,,,,,,,,,,,,,, +Laser Ready,LASER READY,,,,,,,,,,,,,,,,,,,,,, +You Are On The Blue Team,YOU ARE ON THE BLUE TEAM,,,,,,,,,,,,,,,,,,,,,, +You Are On The Red Team,YOU ARE ON THE RED TEAM,,,,,,,,,,,,,,,,,,,,,, +You Got The Enemy Flag...Take It Back To Your Banner,YOU GOT THE ENEMY FLAG...TAKE IT BACK TO YOUR BANNER,,,,,,,,,,,,,,,,,,,,,, +You Got The Beast Flag,YOU GOT THE BEAST FLAG,,,,,,,,,,,,,,,,,,,,,, +You Have Become A Beast,YOU HAVE BECOME A BEAST,,,,,,,,,,,,,,,,,,,,,, +Blue Team Wins,BLUE TEAM WINS,,,,,,,,,,,,,,,,,,,,,, +Red Team Wins,RED TEAM WINS,,,,,,,,,,,,,,,,,,,,,, +Mines ( 5),MINES ( 5),,,,,,,,,,,,,,,,,,,,,, +Medikit Used,MEDIKIT USED,,,,,,,,,,,,,,,,,,,,,, +Explosives,EXPLOSIVES,,,,,,,,,,,,,,,,,,,,,, +Explosives Placed,EXPLOSIVES PLACED,,,,,,,,,,,,,,,,,,,,,, +Press Space To View Map,PRESS SPACE TO VIEW MAP,,,,,,,,,,,,,,,,,,,,,, +Can't Pick Up Artillery Ammo,CAN'T PICK UP ARTILLERY AMMO,,,,,,,,,,,,,,,,,,,,,, +Booze!,BOOZE!,,,,,,,,,,,,,,,,,,,,,, +Booby Trap !!!,BOOBY TRAP !!!,,,,,,,,,,,,,,,,,,,,,, +Mine Detector,MINE DETECTOR,,,,,,,,,,,,,,,,,,,,,, +Radioman - Calling In Fire Mission (Smoke),RADIOMAN - CALLING IN FIRE MISSION (SMOKE),,,,,,,,,,,,,,,,,,,,,, +Ammo For M2machine Gun!,AMMO FOR M2MACHINE GUN!,,,,,,,,,,,,,,,,,,,,,, +M2machine Gun [Press Space To Fire],M2MACHINE GUN [PRESS SPACE TO FIRE],,,,,,,,,,,,,,,,,,,,,, +You're Bleeding,YOU'RE BLEEDING,,,,,,,,,,,,,,,,,,,,,, +A-Gunner,A-GUNNER,,,,,,,,,,,,,,,,,,,,,, +Machine Gunner,MACHINE GUNNER,,,,,,,,,,,,,,,,,,,,,, +Sniper,SNIPER,,,,,,,,,,,,,,,,,,,,,, +Grenadier,GRENADIER,,,,,,,,,,,,,,,,,,,,,, +Point Man,POINT MAN,,,,,,,,,,,,,,,,,,,,,, +Medic,MEDIC,,,,,,,,,,,,,,,,,,,,,, +Squad Leader,SQUAD LEADER,,,,,,,,,,,,,,,,,,,,,, +Killed In Action,KILLED IN ACTION,,,,,,,,,,,,,,,,,,,,,, +Booby Trap Disarmed,BOOBY TRAP DISARMED,,,,,,,,,,,,,,,,,,,,,, +M-60 Machine Gun [Press Space To Fire],M-60 MACHINE GUN [PRESS SPACE TO FIRE],,,,,,,,,,,,,,,,,,,,,, +[Drop Ammo],[DROP AMMO],,,,,,,,,,,,,,,,,,,,,, +[C-4],[C-4],,,,,,,,,,,,,,,,,,,,,, +[Flare],[FLARE],,,,,,,,,,,,,,,,,,,,,, +[Heal],[HEAL],,,,,,,,,,,,,,,,,,,,,, +[Fire Mission],[FIRE MISSION],,,,,,,,,,,,,,,,,,,,,, +[More Ammo],[MORE AMMO],,,,,,,,,,,,,,,,,,,,,, +Medical Supplies,MEDICAL SUPPLIES,,,,,,,,,,,,,,,,,,,,,, +Viet Cong Ammunition,VIET CONG AMMUNITION,,,,,,,,,,,,,,,,,,,,,, +Rotten Food,ROTTEN FOOD,,,,,,,,,,,,,,,,,,,,,, +Sniper Rifle!,SNIPER RIFLE!,,,,,,,,,,,,,,,,,,,,,, +60mm Mortar,60MM MORTAR,,,,,,,,,,,,,,,,,,,,,, +Defend This Position Until Further Orders,DEFEND THIS POSITION UNTIL FURTHER ORDERS,,,,,,,,,,,,,,,,,,,,,, +Shortest }{{{{{{ Longest,SHORTEST }{{{{{{ LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest }}{{{{{ Longest,SHORTEST }}{{{{{ LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest }}}{{{{ Longest,SHORTEST }}}{{{{ LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest }}}}{{{ Longest,SHORTEST }}}}{{{ LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest }}}}}{{ Longest,SHORTEST }}}}}{{ LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest }}}}}}{ Longest,SHORTEST }}}}}}{ LONGEST,,,,,,,,,,,,,,,,,,,,,, +Shortest }}}}}}} Longest,SHORTEST }}}}}}} LONGEST,,,,,,,,,,,,,,,,,,,,,, +Engineer,ENGINEER,,,,,,,,,,,,,,,,,,,,,, +Can't Proceed Without Private Mccurkee!,CAN'T PROCEED WITHOUT PRIVATE McCURKEE!,,,,,,,,,,,,,,,,,,,,,, +Using A Special Skill...,USING A SPECIAL SKILL...,,,,,,,,,,,,,,,,,,,,,, +Defend This Position Until Reinforcements Arrive,DEFEND THIS POSITION UNTIL REINFORCEMENTS ARRIVE,,,,,,,,,,,,,,,,,,,,,, +Reinforcements Have Arrived,REINFORCEMENTS HAVE ARRIVED,,,,,,,,,,,,,,,,,,,,,, +< Empty >,< EMPTY >,,,,,,,,,,,,,,,,,,,,,, +Your Morale Is Weakening,YOUR MORALE IS WEAKENING,,,,,,,,,,,,,,,,,,,,,, +You Are Panicking,YOU ARE PANICKING,,,,,,,,,,,,,,,,,,,,,, +You Are Becoming Insane,YOU ARE BECOMING INSANE,,,,,,,,,,,,,,,,,,,,,, +Giving Firstaid...,GIVING FIRSTAID...,,,,,,,,,,,,,,,,,,,,,, +Mine Detector On,MINE DETECTOR ON,,,,,,,,,,,,,,,,,,,,,, +Giving Firstaid Fast...,GIVING FIRSTAID FAST...,,,,,,,,,,,,,,,,,,,,,, +Mine Detector Off,MINE DETECTOR OFF,,,,,,,,,,,,,,,,,,,,,, +You Are In Red Team,YOU ARE IN RED TEAM,,,,,,,,,,,,,,,,,,,,,, +You Are In Blue Team,YOU ARE IN BLUE TEAM,,,,,,,,,,,,,,,,,,,,,, +Choose Team,CHOOSE TEAM,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +D Day,D DAY,,,,,,,,,,,,,,,,,,,,,, +France,FRANCE,,,,,,,,,,,,,,,,,,,,,, +Multiplayer I,MULTIPLAYER I,,,,,,,,,,,,,,,,,,,,,, +Multiplayer Ii,MULTIPLAYER II,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Draftee,DRAFTEE,,,,,,,,,,,,,,,,,,,,,, +GI,GI,,,,,,,,,,,,,,,,,,,,,, +Paratrooper,PARATROOPER,,,,,,,,,,,,,,,,,,,,,, +Veteran,VETERAN,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Atlantic Wall,ATLANTIC WALL,,,,,,,,,,,,,,,,,,,,,, +Defend,DEFEND,,,,,,,,,,,,,,,,,,,,,, +Hunt For The 88'S,HUNT FOR THE 88'S,,,,,,,,,,,,,,,,,,,,,, +Finding Private Mccurkee,FINDING PRIVATE McCURKEE,,,,,,,,,,,,,,,,,,,,,, +Saving Private Mccurkee,SAVING PRIVATE McCURKEE,,,,,,,,,,,,,,,,,,,,,, +Mop Up,MOP UP,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Hell From Above,HELL FROM ABOVE,,,,,,,,,,,,,,,,,,,,,, +Seaside Sweep,SEASIDE SWEEP,,,,,,,,,,,,,,,,,,,,,, +Under Fire,UNDER FIRE,,,,,,,,,,,,,,,,,,,,,, +Paperwork,PAPERWORK,,,,,,,,,,,,,,,,,,,,,, +Railroad Typhoon,RAILROAD TYPHOON,,,,,,,,,,,,,,,,,,,,,, +A Game Of Bridge,A GAME OF BRIDGE,,,,,,,,,,,,,,,,,,,,,, +Urban Rush,URBAN RUSH,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Mole Hill [Gimatch],MOLE HILL [GIMATCH],,,,,,,,,,,,,,,,,,,,,, +Monastery [Gimatch],MONASTERY [GIMATCH],,,,,,,,,,,,,,,,,,,,,, +Cavefear2 [Gimatch],CAVEFEAR2 [GIMATCH],,,,,,,,,,,,,,,,,,,,,, +Bastogne Boyz [Gimatch],BASTOGNE BOYZ [GIMATCH],,,,,,,,,,,,,,,,,,,,,, +Small Town [Gimatch],SMALL TOWN [GIMATCH],,,,,,,,,,,,,,,,,,,,,, +Town Ruins [Gimatch],TOWN RUINS [GIMATCH],,,,,,,,,,,,,,,,,,,,,, +Fuhrer's Bunker [Gimatch],FUHRER'S BUNKER [GIMATCH],,,,,,,,,,,,,,,,,,,,,, +Good Night [Gimatch],GOOD NIGHT [GIMATCH],,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +D Day [Fireteam],D DAY [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +Seaside Sweep [Fireteam],SEASIDE SWEEP [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +Paperwork [Fireteam],PAPERWORK [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +Hunt For The 88'S [Fireteam],HUNT FOR THE 88'S [FIRETEAM],,,,,,,,,,,,,,,,,,,,,, +D Day [Ctf],D DAY [CTF],,,,,,,,,,,,,,,,,,,,,, +City In Ruins [Ctf],CITY IN RUINS [CTF],,,,,,,,,,,,,,,,,,,,,, +Hedgerow Hell [Ctf],HEDGEROW HELL [CTF],,,,,,,,,,,,,,,,,,,,,, +Casino De Ouistreham [Ctf],CASINO DE OUISTREHAM [CTF],,,,,,,,,,,,,,,,,,,,,, +,Redneck Rampage,,,,,,,,,,,,,,,,,,,,,, +Auto Aimin'...,AUTO AIMIN'...,,,,,,,,,,,,,,,,,,,,,, +Show Yer Map: OFF,SHOW YER MAP: OFF,,,,,,,,,,,,,,,,,,,,,, +Turned On!,TURNED ON!,,,,,,,,,,,,,,,,,,,,,, +Cheap Ass Whiskey...,CHEAP ASS WHISKEY...,,,,,,,,,,,,,,,,,,,,,, +Locked!,LOCKED!,,,,,,,,,,,,,,,,,,,,,, +Take It All!,TAKE IT ALL!,,,,,,,,,,,,,,,,,,,,,, +Hip Waders...,HIP WADERS...,,,,,,,,,,,,,,,,,,,,,, +Wasted!,WASTED!,,,,,,,,,,,,,,,,,,,,,, +Unlocked,UNLOCKED,,,,,,,,,,,,,,,,,,,,,, +Yer Secret Place!,YER SECRET PLACE!,,,,,,,,,,,,,,,,,,,,,, +Squashed Like A Bug!,SQUASHED LIKE A BUG!,,,,,,,,,,,,,,,,,,,,,, +All Doors Unlocked,ALL DOORS UNLOCKED,,,,,,,,,,,,,,,,,,,,,, +You's On A Rampage!!!,YOU'S ON A RAMPAGE!!!,,,,,,,,,,,,,,,,,,,,,, +Mash Activator Key To Kill Again!,MASH ACTIVATOR KEY TO KILL AGAIN!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Alien Arm Gun!!!,AMMO FOR ALIEN ARM GUN!!!,,,,,,,,,,,,,,,,,,,,,, +Turned Off...,TURNED OFF...,,,,,,,,,,,,,,,,,,,,,, +Switch Operated Only!,SWITCH OPERATED ONLY!,,,,,,,,,,,,,,,,,,,,,, +Elvis Lives!,ELVIS LIVES!,,,,,,,,,,,,,,,,,,,,,, +The King Is Dead!,THE KING IS DEAD!,,,,,,,,,,,,,,,,,,,,,, +Dee-Lishus Goo Goo Cluster!,DEE-LISHUS GOO GOO CLUSTER!,,,,,,,,,,,,,,,,,,,,,, +Wussy Aimin' Device: ON,WUSSY AIMIN' DEVICE: ON,,,,,,,,,,,,,,,,,,,,,, +Wussy Aimin' Device: OFF,WUSSY AIMIN' DEVICE: OFF,,,,,,,,,,,,,,,,,,,,,, +"Hell, I Thought You Was A Killbilly!","HELL, I THOUGHT YOU WAS A KILLBILLY!",,,,,,,,,,,,,,,,,,,,,, +Writin': ON,WRITIN': ON,,,,,,,,,,,,,,,,,,,,,, +Writin': OFF,WRITIN': OFF,,,,,,,,,,,,,,,,,,,,,, +Type The Cheat Code:,TYPE THE CHEAT CODE:,,,,,,,,,,,,,,,,,,,,,, +Yer Sound: ON,YER SOUND: ON,,,,,,,,,,,,,,,,,,,,,, +Yer Sound: OFF,YER SOUND: OFF,,,,,,,,,,,,,,,,,,,,,, +Yer Screen Captured And Jailed!,YER SCREEN CAPTURED AND JAILED!,,,,,,,,,,,,,,,,,,,,,, +Xxx Moonshine!,XXX MOONSHINE!,,,,,,,,,,,,,,,,,,,,,, +Vacuum Cleaner Hose Snorkel System,VACUUM CLEANER HOSE SNORKEL SYSTEM,,,,,,,,,,,,,,,,,,,,,, +Press F1 Fer Help,PRESS F1 FER HELP,,,,,,,,,,,,,,,,,,,,,, +Ain't Got The Key!,AIN'T GOT THE KEY!,,,,,,,,,,,,,,,,,,,,,, +Skeleton Key!,SKELETON KEY!,,,,,,,,,,,,,,,,,,,,,, +Rat Aimin' Off,RAT AIMIN' OFF,,,,,,,,,,,,,,,,,,,,,, +Rat Aimin' On,RAT AIMIN' ON,,,,,,,,,,,,,,,,,,,,,, +Cheat Code: Unrecognized,CHEAT CODE: UNRECOGNIZED,,,,,,,,,,,,,,,,,,,,,, +Teat Gun Ammo !,TEAT GUN AMMO !,,,,,,,,,,,,,,,,,,,,,, +Ripsaw Ammo !,RIPSAW AMMO !,,,,,,,,,,,,,,,,,,,,,, +Cheater! You Used The,CHEATER! YOU USED THE,,,,,,,,,,,,,,,,,,,,,, +Cheat To Come Back Alive,CHEAT TO COME BACK ALIVE,,,,,,,,,,,,,,,,,,,,,, +No Savin' Or Loadin' Fer Psyco,NO SAVIN' OR LOADIN' FER PSYCO,,,,,,,,,,,,,,,,,,,,,, +Huntin' Rifle!,HUNTIN' RIFLE!,,,,,,,,,,,,,,,,,,,,,, +Dyn-O-Mite!,DYN-O-MITE!,,,,,,,,,,,,,,,,,,,,,, +Crossbow!,CROSSBOW!,,,,,,,,,,,,,,,,,,,,,, +Yer Scattergun!,YER SCATTERGUN!,,,,,,,,,,,,,,,,,,,,,, +Powder Keg!,POWDER KEG!,,,,,,,,,,,,,,,,,,,,,, +Alien Teat Gun!,ALIEN TEAT GUN!,,,,,,,,,,,,,,,,,,,,,, +Bowling Ball!!,BOWLING BALL!!,,,,,,,,,,,,,,,,,,,,,, +Ripsaw!!,RIPSAW!!,,,,,,,,,,,,,,,,,,,,,, +Large Pork Rinds!,LARGE PORK RINDS!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Rifle!,AMMO FOR RIFLE!,,,,,,,,,,,,,,,,,,,,,, +Ammo For Crossbow!,AMMO FOR CROSSBOW!,,,,,,,,,,,,,,,,,,,,,, +Speedloader!,SPEEDLOADER!,,,,,,,,,,,,,,,,,,,,,, +Hip Waders Off,HIP WADERS OFF,,,,,,,,,,,,,,,,,,,,,, +Hip Waders On,HIP WADERS ON,,,,,,,,,,,,,,,,,,,,,, +Yer Scattergun Shells!,YER SCATTERGUN SHELLS!,,,,,,,,,,,,,,,,,,,,,, +Some Kind Of Key Required,SOME KIND OF KEY REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Some Other Kind Of Key Required,SOME OTHER KIND OF KEY REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Yet Even Another Kind Of Key Required,YET EVEN ANOTHER KIND OF KEY REQUIRED,,,,,,,,,,,,,,,,,,,,,, +Yer Weapon Lowered,YER WEAPON LOWERED,,,,,,,,,,,,,,,,,,,,,, +Yer Weapon Raised,YER WEAPON RAISED,,,,,,,,,,,,,,,,,,,,,, +Hip Waders On,HIP WADERS ON,,,,,,,,,,,,,,,,,,,,,, +Vaccum Cleaner Hose Snorkel On!,VACCUM CLEANER HOSE SNORKEL ON!,,,,,,,,,,,,,,,,,,,,,, +Haulin' Ass Mode Off...,HAULIN' ASS MODE OFF...,,,,,,,,,,,,,,,,,,,,,, +Haulin' Ass Mode On!!!,HAULIN' ASS MODE ON!!!,,,,,,,,,,,,,,,,,,,,,, +Alien Arm Gun,ALIEN ARM GUN,,,,,,,,,,,,,,,,,,,,,, +Cow Pie!,COW PIE!,,,,,,,,,,,,,,,,,,,,,, +Vacuum Cleaner Snorkle,VACUUM CLEANER SNORKLE,,,,,,,,,,,,,,,,,,,,,, +Xxx Moonshine,XXX MOONSHINE,,,,,,,,,,,,,,,,,,,,,, +Beer,BEER,,,,,,,,,,,,,,,,,,,,,, +For You Grandpa!,FOR YOU GRANDPA!,,,,,,,,,,,,,,,,,,,,,, +All Locks Toggled,ALL LOCKS TOGGLED,,,,,,,,,,,,,,,,,,,,,, +What The!,WHAT THE!,,,,,,,,,,,,,,,,,,,,,, +You Were All Wrong!,YOU WERE ALL WRONG!,,,,,,,,,,,,,,,,,,,,,, +Good'n!,GOOD'N!,,,,,,,,,,,,,,,,,,,,,, +Bad'n...,BAD'N...,,,,,,,,,,,,,,,,,,,,,, +You're Burnin'!,YOU'RE BURNIN'!,,,,,,,,,,,,,,,,,,,,,, +Clippin': OFF,CLIPPIN': OFF,,,,,,,,,,,,,,,,,,,,,, +Clippin': ON,CLIPPIN': ON,,,,,,,,,,,,,,,,,,,,,, +You Done Killed 'Em All!,YOU DONE KILLED 'EM ALL!,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Outskirts,OUTSKIRTS,,,,,,,,,,,,,,,,,,,,,, +Downtown,DOWNTOWN,,,,,,,,,,,,,,,,,,,,,, +Pissin' Contest,PISSIN' CONTEST,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Wuss,WUSS,,,,,,,,,,,,,,,,,,,,,, +Meejum,MEEJUM,,,,,,,,,,,,,,,,,,,,,, +Hard Ass,HARD ASS,,,,,,,,,,,,,,,,,,,,,, +Killbilly,KILLBILLY,,,,,,,,,,,,,,,,,,,,,, +Psychobilly,PSYCHOBILLY,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Taylor Town,TAYLOR TOWN,,,,,,,,,,,,,,,,,,,,,, +Lumberland,LUMBERLAND,,,,,,,,,,,,,,,,,,,,,, +Junkyard,JUNKYARD,,,,,,,,,,,,,,,,,,,,,, +Drive-In,DRIVE-IN,,,,,,,,,,,,,,,,,,,,,, +Dairyair Farms,DAIRYAIR FARMS,,,,,,,,,,,,,,,,,,,,,, +Sewers,SEWERS,,,,,,,,,,,,,,,,,,,,,, +Smeltin' Plant,SMELTIN' PLANT,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Downtown Hickston,DOWNTOWN HICKSTON,,,,,,,,,,,,,,,,,,,,,, +Nut House,NUT HOUSE,,,,,,,,,,,,,,,,,,,,,, +J.Cluck's!,J.CLUCK'S!,,,,,,,,,,,,,,,,,,,,,, +The Ruins,THE RUINS,,,,,,,,,,,,,,,,,,,,,, +Grimley's Mortuary,GRIMLEY'S MORTUARY,,,,,,,,,,,,,,,,,,,,,, +Uranium Mines,URANIUM MINES,,,,,,,,,,,,,,,,,,,,,, +Beaudry Mansion,BEAUDRY MANSION,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Country Livin',COUNTRY LIVIN',,,,,,,,,,,,,,,,,,,,,, +Barnyard Hijinks,BARNYARD HIJINKS,,,,,,,,,,,,,,,,,,,,,, +Condemned,CONDEMNED,,,,,,,,,,,,,,,,,,,,,, +Used Cars,USED CARS,,,,,,,,,,,,,,,,,,,,,, +Trainspotting,TRAINSPOTTING,,,,,,,,,,,,,,,,,,,,,, +Mud Alley!,MUD ALLEY!,,,,,,,,,,,,,,,,,,,,,, +The Factory,THE FACTORY,,,,,,,,,,,,,,,,,,,,,, +,Redneck Rides again,,,,,,,,,,,,,,,,,,,,,, +Got Some Wheels!,GOT SOME WHEELS!,,,,,,,,,,,,,,,,,,,,,, +Ohhhhhhh Noooooooooooo!,OHHHHHHH NOOOOOOOOOOOO!,,,,,,,,,,,,,,,,,,,,,, +Now Yer Fucked!!!,NOW YER FUCKED!!!,,,,,,,,,,,,,,,,,,,,,, +Boat Mode Off,BOAT MODE OFF,,,,,,,,,,,,,,,,,,,,,, +No More Cheatin',NO MORE CHEATIN',,,,,,,,,,,,,,,,,,,,,, +Instadrunk!,INSTADRUNK!,,,,,,,,,,,,,,,,,,,,,, +Instasober,INSTASOBER,,,,,,,,,,,,,,,,,,,,,, +Sea Sick Mode On,SEA SICK MODE ON,,,,,,,,,,,,,,,,,,,,,, +Sea Sick Mode Off,SEA SICK MODE OFF,,,,,,,,,,,,,,,,,,,,,, +Motorcycle Gun Ammo!,MOTORCYCLE GUN AMMO!,,,,,,,,,,,,,,,,,,,,,, +Got A Boat!,GOT A BOAT!,,,,,,,,,,,,,,,,,,,,,, +Boat Mode On,BOAT MODE ON,,,,,,,,,,,,,,,,,,,,,, +Boat Gun Mortars!,BOAT GUN MORTARS!,,,,,,,,,,,,,,,,,,,,,, +Chicken Mode!!!!!!!!,CHICKEN MODE!!!!!!!!,,,,,,,,,,,,,,,,,,,,,, +Chicken Crossbow Ammo!!,CHICKEN CROSSBOW AMMO!!,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Land Of The Lost,LAND OF THE LOST,,,,,,,,,,,,,,,,,,,,,, +Homeward Bound,HOMEWARD BOUND,,,,,,,,,,,,,,,,,,,,,, +Pissin' Contest,PISSIN' CONTEST,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Area 69,AREA 69,,,,,,,,,,,,,,,,,,,,,, +Camino Del Diablo,CAMINO DEL DIABLO,,,,,,,,,,,,,,,,,,,,,, +El Peso,EL PESO,,,,,,,,,,,,,,,,,,,,,, +Jack O' Lope Farm,JACK O' LOPE FARM,,,,,,,,,,,,,,,,,,,,,, +Wako,WAKO,,,,,,,,,,,,,,,,,,,,,, +"El Peso, Again","EL PESO, AGAIN",,,,,,,,,,,,,,,,,,,,,, +Refinery,REFINERY,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Sunny Shores,SUNNY SHORES,,,,,,,,,,,,,,,,,,,,,, +Gamblin' Boat,GAMBLIN' BOAT,,,,,,,,,,,,,,,,,,,,,, +Lummockston,LUMMOCKSTON,,,,,,,,,,,,,,,,,,,,,, +Disgraceland,DISGRACELAND,,,,,,,,,,,,,,,,,,,,,, +Moto Madness,MOTO MADNESS,,,,,,,,,,,,,,,,,,,,,, +Brothel,BROTHEL,,,,,,,,,,,,,,,,,,,,,, +Back To Hickston,BACK TO HICKSTON,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Pipe Dreams,PIPE DREAMS,,,,,,,,,,,,,,,,,,,,,, +Swamp Buggies,SWAMP BUGGIES,,,,,,,,,,,,,,,,,,,,,, +Square Dancin',SQUARE DANCIN',,,,,,,,,,,,,,,,,,,,,, +Hog Wild,HOG WILD,,,,,,,,,,,,,,,,,,,,,, +Road Rage,ROAD RAGE,,,,,,,,,,,,,,,,,,,,,, +Snake Canyon,SNAKE CANYON,,,,,,,,,,,,,,,,,,,,,, +Luck Sore,LUCK SORE,,,,,,,,,,,,,,,,,,,,,, +,Route 66,,,,,,,,,,,,,,,,,,,,,, +Route 66 - Part 1,ROUTE 66 - PART 1,,,,,Route 66 - Teil 1,,,,,,,,,,,,,,,,, +Route 66 - Part 2,ROUTE 66 - PART 2,,,,,Route 66 - Teil 2,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Hit The Road,HIT THE ROAD,,,,,Auf Achse,,,,,,,,,,,,,,,,, +Carnival Of Terror,CARNIVAL OF TERROR,,,,,Kirmes des Terrors,,,,,,,,,,,,,,,,, +Big Bertha's,BIG BERTHA'S,,,,,,,,,,,,,,,,,,,,,, +Big Billy's Brewery,BIG BILLY'S BREWERY,,,,,Big Billys Brauerei,,,,,,,,,,,,,,,,, +Flea Market,FLEA MARKET,,,,,Flohmarkt,,,,,,,,,,,,,,,,, +Slaughterhouse,SLAUGHTERHOUSE,,,,,Schlachthaus,,,,,,,,,,,,,,,,, +Fun Park,FUN PARK,,,,,Freizeitpark,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Gassin' Up,GASSIN' UP,,,,,,,,,,,,,,,,,,,,,, +House Of Ill Repute,HOUSE OF ILL REPUTE,,,,,Haus des miesen Rufs,,,,,,,,,,,,,,,,, +Mystery Dino Cave,MYSTERY DINO CAVE,,,,,"Geheimnisvolle Dinohöhle +",,,,,,,,,,,,,,,,, +Campy Crystal Lake,CAMPY CRYSTAL LAKE,,,,,,,,,,,,,,,,,,,,,, +Bigfoot Convention,BIGFOOT CONVENTION,,,,,,,,,,,,,,,,,,,,,, +Hoover Dam,HOOVER DAM,,,,,Hoover Damm,,,,,,,,,,,,,,,,, +Oddity Museum,ODDITY MUSEUM,,,,,Kuriosiätenmuseum,,,,,,,,,,,,,,,,, +,Texts extracted from the source (Duke Nukem),,,,,,,,,,,,,,,,,,,,,, +Come Get Some!,COMEGETSOME,,,,,,,,,,,,,,,,,,,,,, +On (2),TXT_ON2,,,,,An (2),,,,,,,,,,,,,,,,, +Loading,TXT_LOADING,,,,,Laden,,,,,,,,,,,,,,,,, +Loading User Map,TXT_LOADUM,,,,,Lade Benutzerlevel,,,,,,,,,,,,,,,,, +Loading map,TXT_LOADMAP,,,,,Lade Level,,,,,,,,,,,,,,,,, +Entering,TXT_ENTERING,,,,Vstupujete do,Betrete,,Enirante,Entrando a:,,Seuraava kohde,Niveau Suivant,Következik,Prossimo livello,çªå…¥é–‹å§‹,입장,Binnenkomen,Wchodzisz,Próxima fase,Próximo nível,,Следующий уровень,Следећи ниво +Multiplayer Totals,Multiplayer Totals,,,,,Mehrspielerergebnis,,,,,,,,,,,,,,,,, +Name,Name,,,,Jméno,Name,,Nomo,Nombre,,Nimi,Nom,Név,Nome,åå‰,ì´ë¦„,Naam,Nazwa,Nome,,,ИмÑ,Име +Frags,Frags,,,,Fragy,,,Ĉesoj,Bajas,,Frägit,,Fragek,Frags,フラグ,플레ì´ì–´ 킬수,Frags,Fragi,,,,Фраги,Фрагови +Deaths,Deaths,,,,Smrti,Tode,,Mortoj,Muertes,,Kuolemat,Morts,Halálok,Morti,デス,사ë§í•œ 횟수,Overlijden,Åšmierci,Mortes,,,Смерти,Смрти +Ping,Ping,,,,,,,,,,,,,,,,,,,,,, +Game Paused,Game Paused,,,,,Spiel pausiert,,,,,,,,,,,,,,,,, +Thanks to all our,Thanks to all our,,,,,Danke an alle,,,,,,,,,,,,,,,,, +fans for giving,fans for giving,,,,,unsere Fans für,,,,,,,,,,,,,,,,, +us big heads.,us big heads.,,,,,ihre Unterstützung.,,,,,,,,,,,,,,,,, +Look for a Duke Nukem 3D,Look for a Duke Nukem 3D,,,,,Haltet bald Ausschau nach,,,,,,,,,,,,,,,,, +sequel soon.,sequel soon.,,,,,dem Duke Nukem 3D Sequel,,,,,,,,,,,,,,,,, +Press any key to continue,Presskey,,,,,Drüclke eine Taste um fortzufahren.,,,,,,,,,,,,,,,,, +Kills,Kills,,,,Zabití,,,Mortigoj,Asesinatos,,Tapot,Victimes,Ölések,Uccisioni,キル,킬수,Doodt,Zabójstwa,Vítimas,,,УбийÑтва,УбиÑтва +Completed,Completed,,,,DokonÄen,Abgeschlossen,,Finita,Completado,,Suoritettu,terminé,Teljesítve,Finito,攻略,완료,Klaar,UkoÅ„czono,Finalizado,,,Уровень завершён,Ðиво завршен +Your Time:,TXT_YOURTIME,,,,,Deine Zeit:,,,,,,,,,,,,,,,,, +Yer Time:,TXT_YERTIME,,,,,Deine Zeit:,,,,,,,,,,,,,,,,, +Par Time:,TXT_PARTIME,,,,,Par Zeit:,,,,,,,,,,,,,,,,, +3D Realms' Time:,TXT_3DRTIME,,,,,3D Realms Zeit:,,,,,,,,,,,,,,,,, +Green Beret's Time:,TXT_3DRTIME,,"Nam, WW2GI",,,Green Berets Zeit:,,,,,,,,,,,,,,,,, +Xatrix Time:,"TXT_XTRTIME +",,,,,Xatrix Zeit:,,,,,,,,,,,,,,,,, +Prev Best Time:,TXT_PREVBEST,,,,,Vorh. Bestzeit:,,,,,,,,,,,,,,,,, +Your Best Time:,"TXT_YOURBEST +",,,,,Deine Bestzeit:,,,,,,,,,,,,,,,,, +New record!,TXT_NEWRECORD,,,,,"Neuer Rekord! +",,,,,,,,,,,,,,,,, +Cheated!,TXT_CHEATED,,,,,Geschummelt!,,,,,,,,,,,,,,,,, +Enemies Killed:,TXT_ENEMIESKILLED,,,,,Tote Feinde:,,,,,,,,,,,,,,,,, +Enemies Left:,TXT_ENEMIESLEFT,,,,,Lebende Feinde:,,,,,,,,,,,,,,,,, +Varmints Killed:,TXT_VARMINTSKILLED,,,,,Totes Ungeziefer:,,,,,,,,,,,,,,,,, +Varmints Left:,TXT_VARMINTSLEFT,,,,,Lebendes Ungeziefer:,,,,,,,,,,,,,,,,, +N/A,TXT_N_A,,,,,N/V,,,,,,,,,,,,,,,,, +Secrets Found:,TXT_SECFND,,,,,Gefundene Geheimnisse,,,,,,,,,,,,,,,,, +Secrets Missed:,TXT_SECMISS,,,,,Verpasste Geheimnisse,,,,,,,,,,,,,,,,, +Vote cast,VOTECAST,,,,,Stimme abgegeben,,,,,,,,,,,,,,,,, +"Press F1 to Accept, F2 to Decline",TXT_PRESSF1_F2,,,,,"Drücke F1 zum Akzeptieren, F2 zum Ablehnen",,,,,,,,,,,,,,,,, +Enterin',TXT_ENTERIN,,,,,Starte,,,,,,,,,,,,,,,,, +Close Encounters,TXT_CLOSEENCOUNTERS,,,,,Unheimliche Begegnung,,,,,,,,,,,,,,,,, +Enterin' User Map,TXT_ENTRUM,,,,,Starte Benutzerlevel,,,,,,,,,,,,,,,,, +Loadin',TXT_LOADIN,,,,,Laden,,,,,,,,,,,,,,,,, +"Loading... +",TXT_LOADING...,,,,,Laden...,,,,,,,,,,,,,,,,, +,Blood,,,,,,,,,,,,,,,,,,,,,, +Still Kicking,STILL KICKING,,,,,Bewegt sich noch,,,,,,,,,,,,,,,,, +Pink On The Inside,PINK ON THE INSIDE,,,,,Innen noch rot,,,,,,,,,,,,,,,,, +Lightly Broiled,LIGHTLY BROILED,,,,,Leicht gegrillt,,,,,,,,,,,,,,,,, +Well Done,WELL DONE,,,,,Durchgebraten,,,,,,,,,,,,,,,,, +Extra Crispy,EXTRA CRISPY,,,,,Extra knusprig,,,,,,,,,,,,,,,,, +Auto run ON,AUTORUNON,,,,,Rennen AN,,,,,,,,,,,,,,,,, +Auto run OFF,AUTORUNOFF,,,,,Rennen AUS,,,,,,,,,,,,,,,,, +Picked up Skull Key,TXTB_ITEM01,,,,,,,,,,,,,,,,,,,,,, +Picked up Eye Key,TXTB_ITEM02,,,,,,,,,,,,,,,,,,,,,, +Picked up Fire Key,TXTB_ITEM03,,,,,,,,,,,,,,,,,,,,,, +Picked up Dagger Key,TXTB_ITEM04,,,,,,,,,,,,,,,,,,,,,, +Picked up Spider Key,TXTB_ITEM05,,,,,,,,,,,,,,,,,,,,,, +Picked up Moon Key,TXTB_ITEM06,,,,,,,,,,,,,,,,,,,,,, +Picked up Key 7,TXTB_ITEM07,,,,,,,,,,,,,,,,,,,,,, +Picked up Doctor's Bag,TXTB_ITEM08,,,,,,,,,,,,,,,,,,,,,, +Picked up Medicine Pouch,TXTB_ITEM09,,,,,,,,,,,,,,,,,,,,,, +Picked up Life Essence,TXTB_ITEM10,,,,,,,,,,,,,,,,,,,,,, +Picked up Life Seed,TXTB_ITEM11,,,,,,,,,,,,,,,,,,,,,, +Picked up Red Potion,TXTB_ITEM12,,,,,,,,,,,,,,,,,,,,,, +Picked up Feather Fall,TXTB_ITEM13,,,,,,,,,,,,,,,,,,,,,, +Picked up Limited Invisibility,TXTB_ITEM14,,,,,,,,,,,,,,,,,,,,,, +Picked up INVULNERABILITY,TXTB_ITEM15,,,,,,,,,,,,,,,,,,,,,, +Picked up Boots of Jumping,TXTB_ITEM16,,,,,,,,,,,,,,,,,,,,,, +Picked up Raven Flight,TXTB_ITEM17,,,,,,,,,,,,,,,,,,,,,, +Picked up Guns Akimbo,TXTB_ITEM18,,,,,,,,,,,,,,,,,,,,,, +Picked up Diving Suit,TXTB_ITEM19,,,,,,,,,,,,,,,,,,,,,, +Picked up Gas mask,TXTB_ITEM20,,,,,,,,,,,,,,,,,,,,,, +Picked up Clone,TXTB_ITEM21,,,,,,,,,,,,,,,,,,,,,, +Picked up Crystal Ball,TXTB_ITEM22,,,,,,,,,,,,,,,,,,,,,, +Picked up Decoy,TXTB_ITEM23,,,,,,,,,,,,,,,,,,,,,, +Picked up Doppleganger,TXTB_ITEM24,,,,,,,,,,,,,,,,,,,,,, +Picked up Reflective shots,TXTB_ITEM25,,,,,,,,,,,,,,,,,,,,,, +Picked up Beast Vision,TXTB_ITEM26,,,,,,,,,,,,,,,,,,,,,, +Picked up ShadowCloak,TXTB_ITEM27,,,,,,,,,,,,,,,,,,,,,, +Picked up Rage shroom,TXTB_ITEM28,,,,,,,,,,,,,,,,,,,,,, +Picked up Delirium Shroom,TXTB_ITEM29,,,,,,,,,,,,,,,,,,,,,, +Picked up Grow shroom,TXTB_ITEM30,,,,,,,,,,,,,,,,,,,,,, +Picked up Shrink shroom,TXTB_ITEM31,,,,,,,,,,,,,,,,,,,,,, +Picked up Death mask,TXTB_ITEM32,,,,,,,,,,,,,,,,,,,,,, +Picked up Wine Goblet,TXTB_ITEM33,,,,,,,,,,,,,,,,,,,,,, +Picked up Wine Bottle,TXTB_ITEM34,,,,,,,,,,,,,,,,,,,,,, +Picked up Skull Grail,TXTB_ITEM35,,,,,,,,,,,,,,,,,,,,,, +Picked up Silver Grail,TXTB_ITEM36,,,,,,,,,,,,,,,,,,,,,, +Picked up Tome,TXTB_ITEM37,,,,,,,,,,,,,,,,,,,,,, +Picked up Black Chest,TXTB_ITEM38,,,,,,,,,,,,,,,,,,,,,, +Picked up Wooden Chest,TXTB_ITEM39,,,,,,,,,,,,,,,,,,,,,, +Picked up Asbestos Armor,TXTB_ITEM40,,,,,,,,,,,,,,,,,,,,,, +Picked up Basic Armor,TXTB_ITEM41,,,,,,,,,,,,,,,,,,,,,, +Picked up Body Armor,TXTB_ITEM42,,,,,,,,,,,,,,,,,,,,,, +Picked up Fire Armor,TXTB_ITEM43,,,,,,,,,,,,,,,,,,,,,, +Picked up Spirit Armor,TXTB_ITEM44,,,,,,,,,,,,,,,,,,,,,, +Picked up Super Armor,TXTB_ITEM45,,,,,,,,,,,,,,,,,,,,,, +Picked up Blue Team Base,TXTB_ITEM46,,,,,,,,,,,,,,,,,,,,,, +Picked up Red Team Base,TXTB_ITEM47,,,,,,,,,,,,,,,,,,,,,, +Picked up Blue Flag,TXTB_ITEM48,,,,,,,,,,,,,,,,,,,,,, +Picked up Red Flag,TXTB_ITEM49,,,,,,,,,,,,,,,,,,,,,, +Picked up DUMMY,TXTB_ITEM50,,,,,,,,,,,,,,,,,,,,,, +Picked up Level map,TXTB_ITEM51,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Picked up Spray can,TXTB_AMMO01,,,,,,,,,,,,,,,,,,,,,, +Picked up Bundle of TNT*,TXTB_AMMO02,,,,,,,,,,,,,,,,,,,,,, +Picked up Bundle of TNT,TXTB_AMMO03,,,,,,,,,,,,,,,,,,,,,, +Picked up Case of TNT,TXTB_AMMO04,,,,,,,,,,,,,,,,,,,,,, +Picked up Proximity Detonator,TXTB_AMMO05,,,,,,,,,,,,,,,,,,,,,, +Picked up Remote Detonator,TXTB_AMMO06,,,,,,,,,,,,,,,,,,,,,, +Picked up Trapped Soul,TXTB_AMMO07,,,,,,,,,,,,,,,,,,,,,, +Picked up 4 shotgun shells,TXTB_AMMO08,,,,,,,,,,,,,,,,,,,,,, +Picked up Box of shotgun shells,TXTB_AMMO09,,,,,,,,,,,,,,,,,,,,,, +Picked up A few bullets,TXTB_AMMO10,,,,,,,,,,,,,,,,,,,,,, +Picked up Voodoo Doll,TXTB_AMMO11,,,,,,,,,,,,,,,,,,,,,, +Picked up OBSOLETE,TXTB_AMMO12,,,,,,,,,,,,,,,,,,,,,, +Picked up Full drum of bullets,TXTB_AMMO13,,,,,,,,,,,,,,,,,,,,,, +Picked up Tesla Charge,TXTB_AMMO14,,,,,,,,,,,,,,,,,,,,,, +Picked up OBSOLETE,TXTB_AMMO15,,,,,,,,,,,,,,,,,,,,,, +Picked up OBSOLETE,TXTB_AMMO16,,,,,,,,,,,,,,,,,,,,,, +Picked up Flares,TXTB_AMMO17,,,,,,,,,,,,,,,,,,,,,, +Picked up OBSOLETE,TXTB_AMMO18,,,,,,,,,,,,,,,,,,,,,, +Picked up OBSOLETE,TXTB_AMMO19,,,,,,,,,,,,,,,,,,,,,, +Picked up Gasoline Can,TXTB_AMMO20,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Picked up RANDOM,TXTB_WPN01,,,,,,,,,,,,,,,,,,,,,, +Picked up Sawed-off,TXTB_WPN02,,,,,,,,,,,,,,,,,,,,,, +Picked up Tommy Gun,TXTB_WPN03,,,,,,,,,,,,,,,,,,,,,, +Picked up Flare Pistol,TXTB_WPN04,,,,,,,,,,,,,,,,,,,,,, +Picked up Voodoo Doll,TXTB_WPN05,,,,,,,,,,,,,,,,,,,,,, +Picked up Tesla Cannon,TXTB_WPN06,,,,,,,,,,,,,,,,,,,,,, +Picked up Napalm Launcher,TXTB_WPN07,,,,,,,,,,,,,,,,,,,,,, +Picked up Pitchfork,TXTB_WPN08,,,,,,,,,,,,,,,,,,,,,, +Picked up Spray Can,TXTB_WPN09,,,,,,,,,,,,,,,,,,,,,, +Picked up Dynamite,TXTB_WPN10,,,,,,,,,,,,,,,,,,,,,, +Picked up Life Leech,TXTB_WPN11,,,,,,,,,,,,,,,,,,,,,, +It's locked,TXTB_LOCKED,,,,,,,,,,,,,,,,,,,,,, +That requires a key.,TXTB_KEY,,,,,,,,,,,,,,,,,,,,,, +%s dropped Blue Flag,"TXTB_DBF +",,,,,,,,,,,,,,,,,,,,,, +%s dropped Red Flag,TXTB_DRF,,,,,,,,,,,,,,,,,,,,,, +%s stole Blue Flag,TXTB_SBF,todo,,,,,,,,,,,,,,,,,,,,, +%s returned Blue Flag,TXTB_RBF,This looks incomplete and broken,,,,,,,,,,,,,,,,,,,,, +%s captured Red Flag!,TXTB_CRF,,,,,,,,,,,,,,,,,,,,,, +You killed yourself!,TXTB_KILLSELF,,,,,,,,,,,,,,,,,,,,,, +I LIVE...AGAIN!!,TXTB_LIVEAGAIN,,,,,,,,,,,,,,,,,,,,,, +%s lives again!,TXTB_LIVESAGAIN,,,,,,,,,,,,,,,,,,,,,, +Level Stats,TXTB_LEVELSTATS,,,,,,,,,,,,,,,,,,,,,, +>>> YOU CHEATED! <<<,TXTB_CHEATED,,,,,,,,,,,,,,,,,,,,,, +Frag Stats,TXTB_FRAGSTATS,,,,,,,,,,,,,,,,,,,,,, +Of,OF,,,,,,,,,,,,,,,,,,,,,, +A secret is revealed.,TXTB_SECRET0,,,,Tajemství odhaleno!,Ein Geheimnis wurde enthüllt!,Ένα μυστικό αποκαλÏφθηκε!,Sekreto estas malkaÅita!,¡Se ha revelado un secreto!,,Sala löydetty!,Vous avez découvert un secret!,Egy rejtekhely feltárva!,È stato svelato un segreto! ,シークレットを解ã明ã‹ã—ãŸ!,비밀 발견!,Een geheim is onthuld!,Znaleziono sekret!,Um segredo foi revelado!,,,Обнаружен тайник!,Тајна је откривена! +You found a secret.,TXTB_SECRET1,,,,,,,,,,,,,,,,,,,,,, +Secrets,TXT_SECRETS,,,,Tajemství,Geheimnisse,,Sekretoj,Secretos,,Salat,,Rejtekhelyek,Segreti,シークレット,ë°í˜€ë‚¸ 비밀,Geheimen,Sekrety,Segredos,,,Тайники,Тајне +You found a Super Secret!,TXT_SUPERSECRET,,,,,Du hast ein Supergeheimnis gefunden!,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,, +Loading Demo,TXTB_LDEMO,,,,,,,,,,,,,,,,,,,,,, +Loading Level,TXTB_LLEVEL,,,,,,,,,,,,,,,,,,,,,, +Cooperative,TXTB_NETGT1,,,,,,,,,,,,,,,,,,,,,, +Bloodbath,TXTB_NETGT2,,,,,,,,,,,,,,,,,,,,,, +Teams,TXTB_NETGT3,,,,,,,,,,,,,,,,,,,,,, +Map Follow Mode,FOLLOW MODE ON,,Blood,,,,,,,,,,,,,,,,,,,, +Map Scroll Mode,FOLLOW MODE OFF," +",Blood,,,,,,,,,,,,,,,,,,,, +You are immortal.,TXTB_GODMODE,,,,,,,,,,,,,,,,,,,,,, +You are mortal.,TXTB_NOTGODMODE,,,,,,,,,,,,,,,,,,,,,, +Paused,TXTB_PAUSED,,,,,,,,,,,,,,,,,,,,,, +Please Wait,TXTB_PLSWAIT,,,,,,,,,,,,,,,,,,,,,, +Unclipped movement.,TXTB_NOCLIP,,,,,,,,,,,,,,,,,,,,,, +Normal movement.,TXTB_NOCLIPOFF,,,,,,,,,,,,,,,,,,,,,, +You have full ammo.,TXTB_FULLAMMO,,,,,,,,,,,,,,,,,,,,,, +You have no ammo.,TXTB_NOAMMO,,,,,,,,,,,,,,,,,,,,,, +You have all weapons.,TXTB_ALLWEAP,,,,,,,,,,,,,,,,,,,,,, +You have no weapons.,TXTB_NOWEAP,,,,,,,,,,,,,,,,,,,,,, +Your inventory is full.,TXTB_FULLINV,,,,,,,,,,,,,,,,,,,,,, +Your inventory is empty.,TXTB_NOINV,,,,,,,,,,,,,,,,,,,,,, +You have full armor.,TXTB_FULLARM,,,,,,,,,,,,,,,,,,,,,, +You have no armor.,TXTB_NOARM,,,,,,,,,,,,,,,,,,,,,, +You have all keys.,TXTB_ALLKEYS,,,,,,,,,,,,,,,,,,,,,, +You have no keys.,TXTB_NOKEYS,,,,,,,,,,,,,,,,,,,,,, +You have infinite ammo.,TXTB_INFAMMO,,,,,,,,,,,,,,,,,,,,,, +You have limited ammo.,TXTB_LIMAMO,,,,,,,,,,,,,,,,,,,,,, +You have the map.,TXTB_ALLMAP,,,,,,,,,,,,,,,,,,,,,, +You have no map.,TXTB_NOALLMAP,,,,,,,,,,,,,,,,,,,,,, +You have no Jumping Boots.,TXTB_JBOOTS,,,,,,,,,,,,,,,,,,,,,, +You have the Jumping Boots.,TXTB_NOJBOOTS,,,,,,,,,,,,,,,,,,,,,, +You are visible.,TXTB_VISIBLE,,,,,,,,,,,,,,,,,,,,,, +You are invisible.,TXTB_INVISIBLE,,,,,,,,,,,,,,,,,,,,,, +You are vulnerable.,TXTB_VULN,,,,,,,,,,,,,,,,,,,,,, +You are invulnerable.,TXTB_INVULN,,,,,,,,,,,,,,,,,,,,,, +You are not delirious.,TXTB_NODELIR,,,,,,,,,,,,,,,,,,,,,, +You are delirious.,TXTB_DELIR,,,,,,,,,,,,,,,,,,,,,, +Kevorkian approves.,TXTB_KEVORKIAN,,,,,,,,,,,,,,,,,,,,,, +You're fired!,TXTB_FIRED,,,,,,,,,,,,,,,,,,,,,, +Ahhh...those were the days.,TXTB_THEDAYS,,,,,,,,,,,,,,,,,,,,,, +Flame retardant!,TXTB_RETARD,,,,,,,,,,,,,,,,,,,,,, +You have half armor.,TXTB_HALFARMOR,,,,,,,,,,,,,,,,,,,,,, +,Blood levels and messages,,,,,,,,,,,,,,,,,,,,,, +The Way of All Flesh,The Way of All Flesh,,Blood,,,,,,,,,,,,,,,,,,,, +Even Death May Die,Even Death May Die,,Blood,,,,,,,,,,,,,,,,,,,, +Farewell to Arms,Farewell to Arms,,Blood,,,,,,,,,,,,,,,,,,,, +Dead Reckoning,Dead Reckoning,,Blood,,,,,,,,,,,,,,,,,,,, +BloodBath,BloodBath,,Blood,,,,,,,,,,,,,,,,,,,, +Post Mortem,Post Mortem,,Blood,,,,,,,,,,,,,,,,,,,, +Cradle to Grave,Cradle to Grave,,Blood,,,,,,,,,,,,,,,,,,,, +Hit the switch to end the level.,Hit the switch to end the level.,,Blood,,,,,,,,,,,,,,,,,,,, +"Slurp, slurp . . .","Slurp, slurp . . .",,Blood,,,,,,,,,,,,,,,,,,,, +OUT! OUT! DAMN SPOT!,OUT! OUT! DAMN SPOT!,,Blood,,,,,,,,,,,,,,,,,,,, +They'll need more of these.,They'll need more of these.,,Blood,,,,,,,,,,,,,,,,,,,, +Nevermore . . .,Nevermore . . .,,Blood,,,,,,,,,,,,,,,,,,,, +Open for Business.,Open for Business.,,Blood,,,,,,,,,,,,,,,,,,,, +I LIVE AGAIN!,I LIVE AGAIN!,,Blood,,,,,,,,,,,,,,,,,,,, +It is sealed shut.,It is sealed shut.,,Blood,,,,,,,,,,,,,,,,,,,, +Wrong Side of the Tracks,Wrong Side of the Tracks,,Blood,,,,,,,,,,,,,,,,,,,, +This probably isn't a good idea.,This probably isn't a good idea.,,Blood,,,,,,,,,,,,,,,,,,,, +You really should consider turning back.,You really should consider turning back.,,Blood,,,,,,,,,,,,,,,,,,,, +Is there a light at the end of the tunnel?,Is there a light at the end of the tunnel?,,Blood,,,,,,,,,,,,,,,,,,,, +Phantom Express,Phantom Express,,Blood,,,,,,,,,,,,,,,,,,,, +I must stop this train!,I must stop this train!,,Blood,,,,,,,,,,,,,,,,,,,, +Safety clamps are in place. This switch is locked.,Safety clamps are in place. This switch is locked.,,Blood,,,,,,,,,,,,,,,,,,,, +Safety clamps disabled.,Safety clamps disabled.,,Blood,,,,,,,,,,,,,,,,,,,, +Internal engine heat rising!,Internal engine heat rising!,,Blood,,,,,,,,,,,,,,,,,,,, +Internal engine heat critical!,Internal engine heat critical!,,Blood,,,,,,,,,,,,,,,,,,,, +Dark Carnival,Dark Carnival,,Blood,,,,,,,,,,,,,,,,,,,, +This doesn't open from this side.,This doesn't open from this side.,,Blood,,,,,,,,,,,,,,,,,,,, +Hit the switch to end the level.,Hit the switch to end the level.,,Blood,,,,,,,,,,,,,,,,,,,, +You're going to the secret level!,You're going to the secret level!,,Blood,,,,,,,,,,,,,,,,,,,, +Congrats! You win a cupie doll!,Congrats! You win a cupie doll!,,Blood,,,,,,,,,,,,,,,,,,,, +Hallowed Grounds,Hallowed Grounds,,Blood,,,,,,,,,,,,,,,,,,,, +The Great Temple,The Great Temple,,Blood,,,,,,,,,,,,,,,,,,,, +I can't believe you found this!,I can't believe you found this!,,Blood,,,,,,,,,,,,,,,,,,,, +"Here, you can have it all.","Here, you can have it all.",,Blood,,,,,,,,,,,,,,,,,,,, +Altar of Stone,Altar of Stone,,Blood,,,,,,,,,,,,,,,,,,,, +House of Horrors,House of Horrors,,Blood,,,,,,,,,,,,,,,,,,,, +Shipwrecked,Shipwrecked,,Blood,,,,,,,,,,,,,,,,,,,, +The door is jammed shut.,The door is jammed shut.,,Blood,,,,,,,,,,,,,,,,,,,, +The Lumber Mill,The Lumber Mill,,Blood,,,,,,,,,,,,,,,,,,,, +Rest for the Wicked,Rest for the Wicked,,Blood,,,,,,,,,,,,,,,,,,,, +You hear hedges rustling nearby.,You hear hedges rustling nearby.,,Blood,,,,,,,,,,,,,,,,,,,, +The Overlooked Hotel,The Overlooked Hotel,,Blood,,,,,,,,,,,,,,,,,,,, +The secret level lies before you.,The secret level lies before you.,,Blood,,,,,,,,,,,,,,,,,,,, +The Haunting,The Haunting,,Blood,,,,,,,,,,,,,,,,,,,, +The Cold Rush,The Cold Rush,,Blood,,,,,,,,,,,,,,,,,,,, +Bowels of the Earth,Bowels of the Earth,,Blood,,,,,,,,,,,,,,,,,,,, +The Lair of Shial,The Lair of Shial,,Blood,,,,,,,,,,,,,,,,,,,, +Thin Ice,Thin Ice,,Blood,,,,,,,,,,,,,,,,,,,, +Ghost Town,Ghost Town,,Blood,,,,,,,,,,,,,,,,,,,, +The Siege,The Siege,,Blood,,,,,,,,,,,,,,,,,,,, +Raw Sewage,Raw Sewage,,Blood,,,,,,,,,,,,,,,,,,,, +The Sick Ward,The Sick Ward,,Blood,,,,,,,,,,,,,,,,,,,, +Spare Parts,Spare Parts,,Blood,,,,,,,,,,,,,,,,,,,, +Failsafes disabled.,Failsafes disabled.,,Blood,,,,,,,,,,,,,,,,,,,, +Disable failsafes first.,Disable failsafes first.,,Blood,,,,,,,,,,,,,,,,,,,, +Monster Bait,Monster Bait,,Blood,,,,,,,,,,,,,,,,,,,, +The Pit of Cerberus,The Pit of Cerberus,,Blood,,,,,,,,,,,,,,,,,,,, +Catacombs,Catacombs,,Blood,,,,,,,,,,,,,,,,,,,, +Butchery Loves Company,Butchery Loves Company,,Blood,,,,,,,,,,,,,,,,,,,, +Breeding Grounds,Breeding Grounds,,Blood,,,,,,,,,,,,,,,,,,,, +Charnel House,Charnel House,,Blood,,,,,,,,,,,,,,,,,,,, +Crystal Lake,Crystal Lake,,Blood,,,,,,,,,,,,,,,,,,,, +Fire and Brimstone,Fire and Brimstone,,Blood,,,,,,,,,,,,,,,,,,,, +The Ganglion Depths,The Ganglion Depths,,Blood,,,,,,,,,,,,,,,,,,,, +In the Flesh,In the Flesh,,Blood,,,,,,,,,,,,,,,,,,,, +The Hall of the Epiphany,The Hall of the Epiphany,,Blood,,,,,,,,,,,,,,,,,,,, +Mall of the Dead,Mall of the Dead,,Blood,,,,,,,,,,,,,,,,,,,, +The Stronghold,The Stronghold,,Blood,,,,,,,,,,,,,,,,,,,, +Winter Wonderland,Winter Wonderland,,Blood,,,,,,,,,,,,,,,,,,,, +Bodies,Bodies,,Blood,,,,,,,,,,,,,,,,,,,, +The Tower,The Tower,,Blood,,,,,,,,,,,,,,,,,,,, +Click!,Click!,,Blood,,,,,,,,,,,,,,,,,,,, +Twin Fortress,Twin Fortress,,Blood,,,,,,,,,,,,,,,,,,,, +Midgard,Midgard,,Blood,,,,,,,,,,,,,,,,,,,, +Fun With Heads,Fun With Heads,,Blood,,,,,,,,,,,,,,,,,,,, +Monolith Building 11,Monolith Building 11,,Blood,,,,,,,,,,,,,,,,,,,, +Power!,Power!,,Blood,,,,,,,,,,,,,,,,,,,, +Area 15,Area 15,,Blood,,,,,,,,,,,,,,,,,,,, +Welcome to Your Life,Welcome to Your Life,,Blood,,,,,,,,,,,,,,,,,,,, +They Are Here,They Are Here,,Blood,,,,,,,,,,,,,,,,,,,, +Public Storage,Public Storage,,Blood,,,,,,,,,,,,,,,,,,,, +Aqueducts,Aqueducts,,Blood,,,,,,,,,,,,,,,,,,,, +Power restored.,Power restored.,,Blood,,,,,,,,,,,,,,,,,,,, +The Ruined Temple,The Ruined Temple,,Blood,,,,,,,,,,,,,,,,,,,, +Forbidden Rituals,Forbidden Rituals,,Blood,,,,,,,,,,,,,,,,,,,, +The Dungeon,The Dungeon,,Blood,,,,,,,,,,,,,,,,,,,, +You must complete the sequence to open this door.,You must complete the sequence to open this door.,,Blood,,,,,,,,,,,,,,,,,,,, +Part one of three in the sequence has been completed.,Part one of three in the sequence has been completed.,,Blood,,,,,,,,,,,,,,,,,,,, +Part two of three in the sequence has been completed.,Part two of three in the sequence has been completed.,,Blood,,,,,,,,,,,,,,,,,,,, +Final part completed. A door has opened.,Final part completed. A door has opened.,,Blood,,,,,,,,,,,,,,,,,,,, +Beauty and the Beast,Beauty and the Beast,,Blood,,,,,,,,,,,,,,,,,,,, +Forgotten Catacombs,Forgotten Catacombs,,Blood,,,,,,,,,,,,,,,,,,,, +Cryptic Passage,Cryptic Passage,,Blood,,,,,,,,,,,,,,,,,,,, +Cryptic BloodBath,Cryptic BloodBath,,Blood,,,,,,,,,,,,,,,,,,,, +Boat Docks,Boat Docks,,Blood,,,,,,,,,,,,,,,,,,,, +Old Opera House,Old Opera House,,Blood,,,,,,,,,,,,,,,,,,,, +Gothic Library,Gothic Library,,Blood,,,,,,,,,,,,,,,,,,,, +Lost Monastery,Lost Monastery,,Blood,,,,,,,,,,,,,,,,,,,, +Steamboat,Steamboat,,Blood,,,,,,,,,,,,,,,,,,,, +Graveyard,Graveyard,,Blood,,,,,,,,,,,,,,,,,,,, +Mountain Pass,Mountain Pass,,Blood,,,,,,,,,,,,,,,,,,,, +Abysmal Mine,Abysmal Mine,,Blood,,,,,,,,,,,,,,,,,,,, +Castle,Castle,,Blood,,,,,,,,,,,,,,,,,,,, +Boggy Creek,Boggy Creek,,Blood,,,,,,,,,,,,,,,,,,,, +Crypt of Despair,Crypt of Despair,,Blood,,,,,,,,,,,,,,,,,,,, +Pits of Blood,Pits of Blood,,Blood,,,,,,,,,,,,,,,,,,,, +Unholy Cathedral,Unholy Cathedral,,Blood,,,,,,,,,,,,,,,,,,,, +Deadly Inspirations,Deadly Inspirations,,Blood,,,,,,,,,,,,,,,,,,,, +,Shadow Warrior,,,,,,,,,,,,,,,,,,,,,, +Enter the Wang,TXTS_EP1,,,,,,,,,,,,,,,,,,,,,, +Code of Honor,TXTS_EP2,,,,,,,,,,,,,,,,,,,,,, +Four levels (Shareware Version),TXTS_EPD1,,,,,,,,,,,,,,,,,,,,,, +Eighteen levels (Full Version Only),TXTS_EPD2,,,,,,,,,,,,,,,,,,,,,, +Tiny grasshopper,TXTS_SK1,,,,,,,,,,,,,,,,,,,,,, +I Have No Fear,TXTS_SK2,,,,,,,,,,,,,,,,,,,,,, +Who Wants Wang,TXTS_SK3,,,,,,,,,,,,,,,,,,,,,, +"No Pain, No Gain",TXTS_SK4,,,,,,,,,,,,,,,,,,,,,, +Got the RED key!,TXTS_KEY1,,,,,,,,,,,,,,,,,,,,,, +Got the BLUE key!,TXTS_KEY2,,,,,,,,,,,,,,,,,,,,,, +Got the GREEN key!,TXTS_KEY3,,,,,,,,,,,,,,,,,,,,,, +Got the YELLOW key!,TXTS_KEY4,,,,,,,,,,,,,,,,,,,,,, +Got the GOLD master key!,TXTS_KEY5,,,,,,,,,,,,,,,,,,,,,, +Got the SILVER master key!,TXTS_KEY6,,,,,,,,,,,,,,,,,,,,,, +Got the BRONZE master key!,TXTS_KEY7,,,,,,,,,,,,,,,,,,,,,, +Got the RED master key!,TXTS_KEY8,,,,,,,,,,,,,,,,,,,,,, +You need a RED key for this door.,TXTS_DOOR1,,,,,,,,,,,,,,,,,,,,,, +You need a BLUE key for this door.,TXTS_DOOR2,,,,,,,,,,,,,,,,,,,,,, +You need a GREEN key for this door.,TXTS_DOOR3,,,,,,,,,,,,,,,,,,,,,, +You need a YELLOW key for this door.,TXTS_DOOR4,,,,,,,,,,,,,,,,,,,,,, +You need a GOLD key for this door.,TXTS_DOOR5,,,,,,,,,,,,,,,,,,,,,, +You need a SILVER key for this door.,TXTS_DOOR6,,,,,,,,,,,,,,,,,,,,,, +You need a BRONZE key for this door.,TXTS_DOOR7,,,,,,,,,,,,,,,,,,,,,, +You need a RED key for this door.,TXTS_DOOR8,,,,,,,,,,,,,,,,,,,,,, +You never going to score.,TXTS_COOKIE1,,,,,,,,,,,,,,,,,,,,,, +26-31-43-82-16-29,TXTS_COOKIE2,,,,,,,,,,,,,,,,,,,,,, +"Sorry, you no win this time, try again.",TXTS_COOKIE3,,,,,,,,,,,,,,,,,,,,,, +You try harder get along. Be a nice man.,TXTS_COOKIE4,,,,,,,,,,,,,,,,,,,,,, +"No man is island, except Lo Wang.",TXTS_COOKIE5,,,,,,,,,,,,,,,,,,,,,, +There is much death in future.,TXTS_COOKIE6,,,,,,,,,,,,,,,,,,,,,, +You should kill all business associates.,TXTS_COOKIE7,,,,,,,,,,,,,,,,,,,,,, +"(c)1997,3DRealms fortune cookie company.",TXTS_COOKIE8,,,,,,,,,,,,,,,,,,,,,, +Your chi attracts many chicks.,TXTS_COOKIE9,,,,,,,,,,,,,,,,,,,,,, +Don't you know you the scum of society!?,TXTS_COOKIE10,,,,,,,,,,,,,,,,,,,,,, +You should not scratch yourself there.,TXTS_COOKIE11,,,,,,,,,,,,,,,,,,,,,, +"Man who stand on toilet, high on pot.",TXTS_COOKIE12,,,,,,,,,,,,,,,,,,,,,, +Man who fart in church sit in own pew.,TXTS_COOKIE13,,,,,,,,,,,,,,,,,,,,,, +Man trapped in pantry has ass in jam.,TXTS_COOKIE14,,,,,,,,,,,,,,,,,,,,,, +Baseball wrong. Man with 4 balls cannot walk.,TXTS_COOKIE15,,,,,,,,,,,,,,,,,,,,,, +Man who buy drowned cat pay for wet pussy.,TXTS_COOKIE16,,,,,,,,,,,,,,,,,,,,,, +Fortune Say:,TXTS_FORTUNE,,,,,,,,,,,,,,,,,,,,,, +Armor Vest +50,TXTS_INV1,,,,,,,,,,,,,,,,,,,,,, +Kevlar Armor Vest +100,TXTS_INV2,,,,,,,,,,,,,,,,,,,,,, +MedKit +20,TXTS_INV3,,,,,,,,,,,,,,,,,,,,,, +Fortune Cookie +50 BOOST,TXTS_INV4,,,,,,,,,,,,,,,,,,,,,, +Portable MedKit,TXTS_INV5,,,,,,,,,,,,,,,,,,,,,, +Gas Bomb,TXTS_INV6,,,,,,,,,,,,,,,,,,,,,, +Flash Bomb,TXTS_INV7,,,,,,,,,,,,,,,,,,,,,, +Caltrops,TXTS_INV8,,,,,,,,,,,,,,,,,,,,,, +Night Vision Goggles,TXTS_INV9,,,,,,,,,,,,,,,,,,,,,, +Repair Kit,TXTS_INV10,,,,,,,,,,,,,,,,,,,,,, +Smoke Bomb,TXTS_INV11,,,,,,,,,,,,,,,,,,,,,, +Fists,TXTS_WEAP1,,,,,,,,,,,,,,,,,,,,,, +Sword,TXTS_WEAP2,,,,,,,,,,,,,,,,,,,,,, +Shurikens,TXTS_WEAP3,,,,,,,,,,,,,,,,,,,,,, +Sticky Bombs,TXTS_WEAP4,,,,,,,,,,,,,,,,,,,,,, +Darts,TXTS_DARTS,,,,,,,,,,,,,,,,,,,,,, +UZI Submachine Gun,TXTS_WEAP5,,,,,,,,,,,,,,,,,,,,,, +Missile Launcher,TXTS_WEAP6,,,,,,,,,,,,,,,,,,,,,, +Nuclear Warhead,TXTS_WEAP7,,,,,,,,,,,,,,,,,,,,,, +Grenade Launcher,TXTS_WEAP8,,,,,,,,,,,,,,,,,,,,,, +Rail Gun,TXTS_WEAP9,,,,,,,,,,,,,,,,,,,,,, +Riot Gun,TXTS_WEAP10,,,,,,,,,,,,,,,,,,,,,, +Guardian Head,TXTS_WEAP11,,,,,,,,,,,,,,,,,,,,,, +Ripper Heart,TXTS_WEAP12,,,,,,,,,,,,,,,,,,,,,, +UZI Clip,TXTS_AMMO5,,,,,,,,,,,,,,,,,,,,,, +Missiles,TXTS_AMMO6,,,,,,,,,,,,,,,,,,,,,, +Heat Seeker Card,TXTS_AMMO7,,,,,,,,,,,,,,,,,,,,,, +Grenade Shells,TXTS_AMMO8,,,,,,,,,,,,,,,,,,,,,, +Rail Gun Rods,TXTS_AMMO9,,,,,,,,,,,,,,,,,,,,,, +Shotshells,TXTS_AMMO10,,,,,,,,,,,,,,,,,,,,,, +Firebursts,TXTS_AMMO11,,,,,,,,,,,,,,,,,,,,,, +Deathcoils,TXTS_AMMO12,,,,,,,,,,,,,,,,,,,,,, +"Automapping ON +",TXTS_AMON,,,,,,,,,,,,,,,,,,,,,, +Automapping OFF,TXTS_AMOFF,,,,,,,,,,,,,,,,,,,,,, +Given Weapon,TXTS_GIVENW,,,,,,,,,,,,,,,,,,,,,, +Add Ammo to Weapon,TXTS_AMMOW,,,,,,,,,,,,,,,,,,,,,, +Added Health,TXTS_ADDEDHEALTH,,,,,,,,,,,,,,,,,,,,,, +Given all keys,TXTS_GIVEKEY,,,,,,,,,,,,,,,,,,,,,, +Key given,TXTS_KEYGIVEN,,,,,,,,,,,,,,,,,,,,,, +Key removed,TXTS_KEYREMOVED,,,,,,,,,,,,,,,,,,,,,, +You're too skillful to cheat,TXTS_TOOSKILLFUL,,,,,,,,,,,,,,,,,,,,,, +Press Space Bar to continue,TXTS_PRESSSPACE,,,,,,,,,,,,,,,,,,,,,, +Press SPACE to restart,TXTS_PRESSSPACER,,,,,,,,,,,,,,,,,,,,,, +%p decided to do the graveyard tour.,TXTS_SUICIDE01,"todo (player.cpp, line 6346ff)",,,,,,,,,,,,,,,,,,,,, +%p had enough and checked out.,TXTS_SUICIDE02,,,,,,,,,,,,,,,,,,,,,, +%p didn't fear the Reaper.,TXTS_SUICIDE03,,,,,,,,,,,,,,,,,,,,,, +%p dialed the 1-800-CYANIDE line.,TXTS_SUICIDE04,,,,,,,,,,,,,,,,,,,,,, +%p wasted himself.,TXTS_SUICIDE05,,,,,,,,,,,,,,,,,,,,,, +%p kicked his own ass.,TXTS_SUICIDE06,,,,,,,,,,,,,,,,,,,,,, +%p went out in blaze of his own glory.,TXTS_SUICIDE07,,,,,,,,,,,,,,,,,,,,,, +%p killed himself before anyone else could.,TXTS_SUICIDE08,,,,,,,,,,,,,,,,,,,,,, +%p needs shooting lessons.,TXTS_SUICIDE09,,,,,,,,,,,,,,,,,,,,,, +%p blew his head off.,TXTS_SUICIDE10,,,,,,,,,,,,,,,,,,,,,, +%p did everyone a favor and offed himself,TXTS_SUICIDE11,,,,,,,,,,,,,,,,,,,,,, +%p was wasted by %k's %z.,TXTS_MPOBIT01,,,,,,,,,,,,,,,,,,,,,, +%p got his ass kicked by %k's %z.,TXTS_MPOBIT02,,,,,,,,,,,,,,,,,,,,,, +%p bows down before the mighty power of %z.,TXTS_MPOBIT03,,,,,,,,,,,,,,,,,,,,,, +%p was killed by %k's %z.,TXTS_MPOBIT04,,,,,,,,,,,,,,,,,,,,,, +%p got slapped down hard by %k's %z.,TXTS_MPOBIT05,,,,,,,,,,,,,,,,,,,,,, +%p got on his knees before %k.,TXTS_MPOBIT06,,,,,,,,,,,,,,,,,,,,,, +%p was totally out classed by %k's %z.,TXTS_MPOBIT07,,,,,,,,,,,,,,,,,,,,,, +%p got chewed apart by %k's %z.,TXTS_MPOBIT08,,,,,,,,,,,,,,,,,,,,,, +%p was retired by %k's %z.,TXTS_MPOBIT09,,,,,,,,,,,,,,,,,,,,,, +%p was greased by %k's %z.,TXTS_MPOBIT10,,,,,,,,,,,,,,,,,,,,,, +%p was humbled lower than dirt by %k.,TXTS_MPOBIT11,,,,,,,,,,,,,,,,,,,,,, +%p beats %k like a red headed step child.,TXTS_MPOBIT12,,,,,,,,,,,,,,,,,,,,,, +%p begs for mercy as %k terminates @[en_ppro] with extreme prejudice.,TXTS_MPOBIT13,,,,,,,,,,,,,,,,,,,,,, +%p falls before the superior skills of %k.,TXTS_MPOBIT14,,,,,,,,,,,,,,,,,,,,,, +%k gives %p a beating @[en_pro] will never forget.,TXTS_MPOBIT15,,,,,,,,,,,,,,,,,,,,,, +%k puts the Smack Dab on %p with the %z.,TXTS_MPOBIT16,,,,,,,,,,,,,,,,,,,,,, +This only opens in single play.,TXTS_SPONLY,,,,,,,,,,,,,,,,,,,,,, +You found a secret area!,TXTS_SECRET,,,,,,,,,,,,,,,,,,,,,, +Zombie,Zombie,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Blood Worm,Blood Worm,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Skeletor Priest,Skeletor Priest,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Coolie Ghost,Coolie Ghost,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Guardian,Guardian,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Hornet,Hornet,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Ripper Hatchling,Ripper Hatchling,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Ripper,Ripper,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Killer Rabbit,Killer Rabbit,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Serpent God,Serpent God,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Girl Ninja,Girl Ninja,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Blade,Blade,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Dart,Dart,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Shuriken,Shuriken,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Crossbow Bolt,Crossbow Bolt,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Spear,Spear,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Lava Boulder,Lava Boulder,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Uzi,Uzi,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Evil Ninja Uzi,Evil Ninja Uzi,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Shotgun,Shotgun,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Meteor,Meteor,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Rocket,Rocket,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Rail Gun,Rail Gun,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Enemy Rocket,Enemy Rocket,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Bunny Rocket,Bunny Rocket,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Explosion,Explosion,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Tank Shell,Tank Shell,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Nuclear Bomb,Nuclear Bomb,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +40mm Grenade,40mm Grenade,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Micro Missile,Micro Missile,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Sticky Bomb,Sticky Bomb,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Napalm,Napalm,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Vomit,Vomit,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Coolie Ghost Phlem,Coolie Ghost Phlem,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Accursed Head,Accursed Head,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Bouncing Betty,Bouncing Betty,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Serpent God Protector,Serpent God Protector,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Flames,Flames,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Radiation,Radiation,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Caltrops,Caltrops,,ShadowWarrior,,,,,,,,,,,,,,,,,,,, +Seppuku Station,TXTS_MAP01,,,,,,,,,,,,,,,,,,,,,, +Zilla Construction,TXTS_MAP02,,,,,,,,,,,,,,,,,,,,,, +Master Leep's Temple,TXTS_MAP03,,,,,,,,,,,,,,,,,,,,,, +Dark Woods of the Serpent,TXTS_MAP04,,,,,,,,,,,,,,,,,,,,,, +Rising Son,TXTS_MAP05,,,,,,,,,,,,,,,,,,,,,, +Killing Fields,TXTS_MAP06,,,,,,,,,,,,,,,,,,,,,, +Hara-Kiri Harbor,TXTS_MAP07,,,,,,,,,,,,,,,,,,,,,, +Zilla's Villa,TXTS_MAP08,,,,,,,,,,,,,,,,,,,,,, +Monastery,TXTS_MAP09,,,,,,,,,,,,,,,,,,,,,, +Raider of the Lost Wang,TXTS_MAP10,,,,,,,,,,,,,,,,,,,,,, +Sumo Sky Palace,TXTS_MAP11,,,,,,,,,,,,,,,,,,,,,, +Bath House,TXTS_MAP12,,,,,,,,,,,,,,,,,,,,,, +Unfriendly Skies,TXTS_MAP13,,,,,,,,,,,,,,,,,,,,,, +Crude Oil,TXTS_MAP14,,,,,,,,,,,,,,,,,,,,,, +Coolie Mines,TXTS_MAP15,,,,,,,,,,,,,,,,,,,,,, +Subpen 7,TXTS_MAP16,,,,,,,,,,,,,,,,,,,,,, +The Great Escape,TXTS_MAP17,,,,,,,,,,,,,,,,,,,,,, +Floating Fortress,TXTS_MAP18,,,,,,,,,,,,,,,,,,,,,, +Water Torture,TXTS_MAP19,,,,,,,,,,,,,,,,,,,,,, +Stone Rain,TXTS_MAP20,,,,,,,,,,,,,,,,,,,,,, +Shanghai Shipwreck,TXTS_MAP21,,,,,,,,,,,,,,,,,,,,,, +Auto Maul,TXTS_MAP22,,,,,,,,,,,,,,,,,,,,,, +Heavy Metal (DM only),TXTS_MAP23,,,,,,,,,,,,,,,,,,,,,, +Ripper Valley (DM only),TXTS_MAP24,,,,,,,,,,,,,,,,,,,,,, +House of Wang (DM only),TXTS_MAP25,,,,,,,,,,,,,,,,,,,,,, +Lo Wang Rally (DM only),TXTS_MAP26,,,,,,,,,,,,,,,,,,,,,, +Ruins of the Ronin (CTF),TXTS_MAP27,,,,,,,,,,,,,,,,,,,,,, +Killing Fields (CTF),TXTS_MAP28,,,,,,,,,,,,,,,,,,,,,, +Chinatown,TXTS_W_MAP01,,,,,,,,,,,,,,,,,,,,,, +Monastery,TXTS_W_MAP02,,,,,,,,,,,,,,,,,,,,,, +Trolly Yard,TXTS_W_MAP03,,,,,,,,,,,,,,,,,,,,,, +Restaurant,TXTS_W_MAP04,,,,,,,,,,,,,,,,,,,,,, +Skyscraper,TXTS_W_MAP05,,,,,,,,,,,,,,,,,,,,,, +Airplane,TXTS_W_MAP06,,,,,,,,,,,,,,,,,,,,,, +Military Base,TXTS_W_MAP07,,,,,,,,,,,,,,,,,,,,,, +Train,TXTS_W_MAP08,,,,,,,,,,,,,,,,,,,,,, +Auto Factory,TXTS_W_MAP09,,,,,,,,,,,,,,,,,,,,,, +Skyline,TXTS_W_MAP10,,,,,,,,,,,,,,,,,,,,,, +Redwood Forest,TXTS_W_MAP11,,,,,,,,,,,,,,,,,,,,,, +The Docks,TXTS_W_MAP12,,,,,,,,,,,,,,,,,,,,,, +Waterfight (DM only),TXTS_W_MAP13,,,,,,,,,,,,,,,,,,,,,, +Wanton DM 1 (DM only),TXTS_W_MAP14,,,,,,,,,,,,,,,,,,,,,, +Wanton DM2 (DM only),TXTS_W_MAP15,,,,,,,,,,,,,,,,,,,,,, +Wanton CTF (CTF),TXTS_W_MAP16,,,,,,,,,,,,,,,,,,,,,, +Wanton Destruction,TXTS_W_EP,,,,,,,,,,,,,,,,,,,,,, +Home Sweet Home,Home Sweet Home,"Twin Dragon +","ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +City of Dispair,City of Dispair,already contains,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Emergency Room,Emergency Room,SWCUSTOM.TXT,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Hide and Seek,Hide and Seek,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Warehouse Madness,Warehouse Madness,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Weapons Research Center,Weapons Research Center,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Toxic Waste Facility,Toxic Waste Facility,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Silver Bullet,Silver Bullet,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Fishing Village,Fishing Village,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Secret Garden,Secret Garden,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Hung Lo's Fortress,Hung Lo's Fortress,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Hung Lo's Palace,Hung Lo's Palace,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Prison Camp (secret level),Prison Camp (secret level),,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Ninja Training Camp (dm),Ninja Training Camp (dm),,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +The Morgue/mortuary (dm),The Morgue/mortuary (dm),,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Island Caves (dm),Island Caves (dm),,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, +Twin Dragon,Twin Dragon,,"ShadowWarrior +",,,,,,,,,,,,,,,,,,,, \ No newline at end of file diff --git a/wadsrc/static/demolition/leftbinds.txt b/wadsrc/static/demolition/leftbinds.txt new file mode 100644 index 000000000..5e991edf4 --- /dev/null +++ b/wadsrc/static/demolition/leftbinds.txt @@ -0,0 +1,15 @@ +// Left handed config (puts as many controls as possible on the numpad. Also more useful actions on the mouse.) +uparrow "+Move_Forward" +downarrow "+Move_Backward" +LCtrl "+Fire" +Space "+Open" +A "+Jump" +KP- "+Jump" +Z "+Crouch" +C "+Toggle_Crouch" +KP. "+Look_Right" +KP7 "+Strafe_Left" +KP9 "+Strafe_Right" +KP. "+Look_Right" +Mouse2 "+Open" +Mouse3 "+Run" diff --git a/wadsrc/static/demolition/menudef.txt b/wadsrc/static/demolition/menudef.txt new file mode 100644 index 000000000..c2a6a68dd --- /dev/null +++ b/wadsrc/static/demolition/menudef.txt @@ -0,0 +1,1734 @@ +//------------------------------------------------------------------------------------------- +// +// Main Memu +// +//------------------------------------------------------------------------------------------- + +LISTMENU "MainMenu" +{ + ScriptId 0 + ifgame(Duke, Nam, WW2GI, Fury, Redneck, RedneckRides) + { + ifgame(fury) + { + position 40, 130, 60 + fixedspacing 2 + } + else + { + position 160, 55, 115 + centermenu + animatedtransition + } + ifgame(Duke, Nam, WW2GI, Fury) + { + class "Duke.MainMenu" + } + else + { + class "Redneck.MainMenu" + } + NativeTextItem "$MNU_NEWGAME", "n", "EpisodeMenu" + //NativeTextItem "$MNU_NEWGAME", "m", "MultiMenu" // In EDuke this replaces "New Game" when in networking mode. Kept here as a reminder. + ifgame(fury) + { + NativeTextItem "$MNU_CONTINUE", "l", "LoadGameMenu" + } + else + { + NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu" + } + NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu" + NativeTextItem "$MNU_HELP", "h", "HelpMenu" + NativeTextItem "$MNU_CREDITS", "c", "CreditsMenu" + NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu" + } + ifgame(Blood) + { + position 160, 45, 150 + caption "Blood" + class "Blood.ListMenu" + centermenu + Linespacing 20 + NativeTextItem "$MNU_NEWGAME", "n", "EpisodeMenu" + NativeTextItem "$MNU_MULTIPLAYER", "m", "MultiMenu" + NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu" + NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu" + NativeTextItem "$MNU_HELP", "h", "HelpMenu" + NativeTextItem "$MNU_CREDITS", "c", "CreditsMenu" + NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu" + } + ifgame(ShadowWarrior) + { + Position 55, 32 + Linespacing 17 + class "ShadowWarrior.MainMenu" + NativeTextItem "$MNU_NEWGAME", "n", "EpisodeMenu" + NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu" + NativeTextItem "$MNU_SAVEGAME", "s", "SaveGameMenu" + NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu" + //NativeTextItem "$MNU_COOLSTUFF", "h", "HelpMenu" // Perfectly useless retro ads. :D + ifshareware(false) + { + NativeTextItem "$MNU_CREDITS", "c", "CreditsMenu" + } + else + { + NativeTextItem "$MNU_HOWTOORDER", "h", "CreditsMenu" + } + NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu" + } +} + +//------------------------------------------------------------------------------------------- +// +// Ingame Memu (same as above with a few more options) +// +//------------------------------------------------------------------------------------------- + +LISTMENU "IngameMenu" +{ + ScriptId 50 + ifgame(Duke, Nam, WW2GI, Fury, Redneck, RedneckRides) + { + ifgame(fury) + { + position 40, 130, 60 + fixedspacing 2 + } + else + { + position 160, 55, 115 + centermenu + animatedtransition + } + ifgame(Duke, Nam, WW2GI, Fury) + { + class "Duke.MainMenu" + } + else + { + class "Redneck.MainMenu" + } + NativeTextItem "$MNU_NEWGAME", "n", "EpisodeMenu" + NativeTextItem "$MNU_SAVEGAME", "s", "SaveGameMenu" + NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu" + NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu" + NativeTextItem "$MNU_HELP", "h", "HelpMenu" + NativeTextItem "$MNU_ENDGAME", "e", "EndgameMenu" + NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu" + } + ifgame(Blood) + { + position 160, 45, 150 + caption "Blood" + class "Blood.ListMenu" + centermenu + Linespacing 17 + NativeTextItem "$MNU_NEWGAME", "n", "EpisodeMenu" + NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu" + NativeTextItem "$MNU_SAVEGAME", "s", "SaveGameMenu" + NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu" + NativeTextItem "$MNU_HELP", "h", "HelpMenu" + NativeTextItem "$MNU_CREDITS", "c", "CreditsMenu" + NativeTextItem "$MNU_ENDGAME", "e", "EndgameMenu" + NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu" + } + ifgame(ShadowWarrior) + { + Position 55, 32 + Linespacing 17 + class "ShadowWarrior.MainMenu" + NativeTextItem "$MNU_NEWGAME", "n", "EpisodeMenu" + NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu" + NativeTextItem "$MNU_SAVEGAME", "s", "SaveGameMenu" + NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu" + ifshareware(false) + { + NativeTextItem "$MNU_CREDITS", "c", "CreditsMenu" + } + else + { + NativeTextItem "$MNU_HOWTOORDER", "h", "CreditsMenu" + } + NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu" + } +} + +//------------------------------------------------------------------------------------------- +// +// Episode and skill menu are filled in programmatically +// +//------------------------------------------------------------------------------------------- + +LISTMENU "EpisodeMenu" +{ + ifgame(Duke, Nam, WW2GI, Fury, Redneck, RedneckRides) // Ion Fury does not use this menu. + { + caption "$MNU_SELECTEPISODE" + position 160, 48, 142 + centermenu + fixedspacing 5 + animatedtransition + ifgame(Duke, Nam, WW2GI, Fury) + { + class "Duke.ListMenu" + } + else + { + class "Redneck.ListMenu" + } + } + ifgame(blood) + { + caption "$MNU_EPISODES" + position 160, 45, 150 + class "Blood.ListMenu" + centermenu + Linespacing 20 + } + ifgame(ShadowWarrior) + { + caption "$MNU_EPISODES" + Position 35, 32 + Linespacing 17 + } + + ScriptId 100 +} + +LISTMENU "SkillMenu" +{ + ifgame(Duke, Nam, WW2GI, Fury, Redneck, RedneckRides) + { + ifgame(fury) + { + position 160, 55, 115 + fixedspacing 2 + } + else + { + position 160, 55, 115 + centermenu + animatedtransition + } + caption "$MNU_SELECTSKILL" + fixedspacing 5 + ifgame(Duke, Nam, WW2GI, Fury) + { + class "Duke.ListMenu" + } + else + { + class "Redneck.ListMenu" + } + animatedtransition + } + ifgame(blood) + { + caption "$MNU_DIFFICULTY" + position 160, 60, 150 + class "Blood.ListMenu" + centermenu + Linespacing 20 + } + ifgame(ShadowWarrior) + { + caption "$MNU_DIFFICULTY" + Position 35, 32 + Linespacing 17 + } + ScriptId 110 +} + +//------------------------------------------------------------------------------------------- +// +// The custom menus are only supported by the EDuke32 frontend. +// +//------------------------------------------------------------------------------------------- + +LISTMENU "CustomGameMenu" +{ + caption "$MNU_NEWGAME" + position 160, 48, 142 + ifgame(fury) + { + fixedspacing 2 + } + else + { + fixedspacing 5 + animatedtransition + } + ScriptId 102 + class "Duke.ListMenu" + centermenu +} + +LISTMENU "CustomSubMenu1" +{ + position 160, 48, 142 + centermenu + ifgame(fury) + { + fixedspacing 2 + } + else + { + fixedspacing 5 + animatedtransition + } + centermenu + ScriptId 103 + class "Duke.ListMenu" +} + +LISTMENU "CustomSubMenu2" +{ + position 160, 48, 142 + ifgame(fury) + { + fixedspacing 2 + } + else + { + fixedspacing 5 + animatedtransition + } + centermenu + ScriptId 103 + class "Duke.ListMenu" +} + +LISTMENU "CustomSubMenu3" +{ + position 160, 48, 142 + ifgame(fury) + { + fixedspacing 2 + } + else + { + fixedspacing 5 + animatedtransition + } + centermenu + ScriptId 103 + class "Duke.ListMenu" +} + +LISTMENU "CustomSubMenu4" +{ + position 160, 48, 142 + ifgame(fury) + { + fixedspacing 2 + } + else + { + fixedspacing 5 + animatedtransition + } + centermenu + ScriptId 103 + class "Duke.ListMenu" +} + +LISTMENU "CustomSubMenu5" +{ + position 160, 48, 142 + ifgame(fury) + { + fixedspacing 2 + } + else + { + fixedspacing 5 + animatedtransition + } + centermenu + ScriptId 103 + class "Duke.ListMenu" +} + +LISTMENU "CustomSubMenu6" +{ + position 160, 48, 142 + ifgame(fury) + { + fixedspacing 2 + } + else + { + fixedspacing 5 + animatedtransition + } + centermenu + ScriptId 103 + class "Duke.ListMenu" +} + +LISTMENU "CustomSubMenu7" +{ + position 160, 48, 142 + ifgame(fury) + { + fixedspacing 2 + } + else + { + fixedspacing 5 + animatedtransition + } + centermenu + ScriptId 103 + class "Duke.ListMenu" +} + +//------------------------------------------------------------------------------------------- +// +// +// +//------------------------------------------------------------------------------------------- + +ImageScroller "HelpMenu" +{ + ifgame(Duke, Nam, WW2GI, Fury) + { + ImageItem "TEXTSTORY", 400 + ImageItem "F1HELP", 401 + class "Duke.ImageScrollerMenu" + ifgame(Duke, Nam, WW2GI) + { + animatedtransition + } + } + ifgame(Redneck, RedneckRides) + { + ImageItem "TEXTSTORY" + ImageItem "F1HELP" + ifgame(RedneckRides) + { + ImageItem "RRTILE1636" + } + animatedtransition + } + ifgame(blood) + { + class "Blood.ImageScrollerMenu" + // The duplication here is to integrate the alternating versions of HELP3 + QAVAnimationItem "Help4.qav" + QAVAnimationItem "Help5.qav" + QAVAnimationItem "Help3.qav" + QAVAnimationItem "Help4.qav" + QAVAnimationItem "Help5.qav" + QAVAnimationItem "Help3b.qav" + } + ifgame(ShadowWarrior) + { + // The menu has no default binding, but if someone tries to open it anyway show the cool retro ads that were shipped with the game. :D + ImageItem "#5262" + ifshareware(false) + { + ImageItem "#5261" + } + } +} + +//------------------------------------------------------------------------------------------- +// +// Credits menu. This is logically highly game specific. +// Note that this has been split into two submenus so that the engine +// credits can be handled in a generic fashion instead of having to define +// them for each game natively. +// +// Engine credits are now in the options menu, i.e. the generic part of the menu. +// +//------------------------------------------------------------------------------------------- + +ImageScroller "CreditsMenu" +{ + ifgame(Duke, Nam, WW2GI) + { + ImageItem "CREDITSTEXT1", 990 + ImageItem "CREDITSTEXT2", 991 + ImageItem "CREDITSTEXT3", 992 + animatedtransition + class "Duke.ImageScrollerMenu" + } + ifgame(fury) + { + // Ion Fury does not have a separate credits menu, so if someone tries to open it anyway, use the same screens as "Help" but start on the one for the credits. + ImageItem "F1HELP", 401 + ImageItem "TEXTSTORY", 400 + class "Duke.ImageScrollerMenu" + } + ifgame(Redneck) + { + // no point putting this into the string table. + TextItem "ORIGINAL CONCEPT, DESIGN AND DIRECTION\n\nDREW MARKHAM", 80 + TextItem "PRODUCED BY\n\nGREG GOODRICH", 80 + TextItem "GAME PROGRAMMING\n\nRAFAEL PAIZ", 80 + TextItem "ART DIRECTORS\n\nCLAIRE PRADERIE MAXX KAUFMAN ", 80 + TextItem "LEAD LEVEL DESIGNER\nALEX MAYBERRY\n\nLEVEL DESIGN\nMAL BLACKWELL\nSVERRE KVERNMO", 80 + TextItem "SENIOR ANIMATOR AND ARTIST\n\nJASON HOOVER", 80 + TextItem "TECHNICAL DIRECTOR\n\nBARRY DEMPSEY", 80 + TextItem "MOTION CAPTURE SPECIALIST AND\nCHARACTER ANIMATION\nAMIT DORON\n\nA.I. PROGRAMMING\nARTHUR DONAVAN\n\nADDITIONAL ANIMATION\nGEORGE KARL", 60 + TextItem "CHARACTER DESIGN\nCORKY LEHMKUHL\n\nMAP PAINTERS\nVIKTOR ANTONOV\nMATTHIAS BEEGUER\nSTEPHAN BURLE\n\nSCULPTORS\nGEORGE ENGEL\nJAKE GARBER\nJEFF HIMMEL", 50 + TextItem "CHARACTER VOICES\n\nLEONARD\nBURTON GILLIAM\n\nBUBBA, BILLY RAY, SKINNY OL' COOT\nAND THE TURD MINION\nDREW MARKHAM\n\nSHERIFF LESTER T. HOBBES\nMOJO NIXON\n\nALIEN VIXEN\nPEGGY JO JACOBS", 40 + TextItem "SOUND DESIGN\nGARY BRADFIELD\n\nMUSIC\nMOJO NIXON\nTHE BEAT FARMERS\nTHE REVEREND HORTON HEAT\nCEMENT POND\n\nADDITIONAL SOUND EFFECTS\nJIM SPURGIN", 50 + TextItem "MOTION CAPTURE ACTOR\nJ.P. MANOUX\n\nMOTION CAPTURE VIXEN\nSHAWN WOLFE", 80 + TextItem "PRODUCTION ASSISTANCE\nMINERVA MAYBERRY\n\nNUTS AND BOLTS\nSTEVE GOLDBERG\nMARCUS HUTCHINSON\n\nBEAN COUNTING\nMAX YOSHIKAWA\n\nADMINISTRATIVE ASSISTANCE\nSERAFIN LEWIS", 50 + TextItem "LOCATION MANAGER, LOUISIANA\nRICK SKINNER\n\nLOCATION SCOUT, LOUISIANA\nBRIAN BENOS\n\nPHOTOGRAPHER\nCARLOS SERRAO", 70 + TextItem "ADDITIONAL 3D MODELING BY\n3 NAME 3D\nVIEWPOINT DATALABS INTERNATIONAL\n\nAUDIO RECORDED AT\nPACIFIC OCEAN POST, SANTA MONICA, C.A.\n\nCEMENT POND TRACKS RECORDED AT\nDREAMSTATE RECORDING, BURBANK, C.A.\n\nRECORDING ENGINEER\nDAVE AHLERT", 50 + TextItem "3D BUILD ENGINE LICENSED FROM\n3D REALMS ENTERTAINMENT\n\nBUILD ENGINE AND RELATED TOOLS\nCREATED BY KEN SILVERMAN", 80 + TextItem "FOR INTERPLAY\n\nLEAD TESTER\nDARRELL JONES\n\nTESTERS\nTIM ANDERSON\nERICK LUJAN\nTIEN TRAN", 60 + TextItem "IS TECHS\nBILL DELK\nAARON MEYERS\n\nCOMPATIBILITY TECHS\nMARC DURAN\nDAN FORSYTH\nDEREK GIBBS\nAARON OLAIZ\nJACK PARKER", 60 + TextItem "DIRECTOR OF COMPATIBILITY\nPHUONG NGUYEN\n\nASSISTANT QA DIRECTOR\nCOLIN TOTMAN\n\nQA DIRECTOR\nCHAD ALLISON", 70 + TextItem "INTERPLAY PRODUCER\nBILL DUGAN\n\nINTERPLAY LINE PRODUCER\nCHRIS BENSON\n\nPRODUCT MANAGER\nJIM VEEVAERT\n\nPUBLIC RELATIONS\nERIKA PRICE", 50 + TextItem "SPECIAL THANKS\n\nJIM GAUER\nPAUL VAIS\nSCOTT MILLER\nTODD REPLOGLE\nCHUCK BUECHE\nCARTER LIPSCOMB\nJOHN CONLEY\nDON MAGGI", 60 + TextItem "EXTRA SPECIAL THANKS\n\nBRIAN FARGO", 80 + TextItem "REDNECK RAMPAGE\n(c) 1997 XATRIX ENTERTAINMENT, INC.\n\nREDNECK RAMPAGE IS A TRADEMARK OF\nINTERPLAY PRODUCTIONS", 60 + animatedtransition + } + ifgame(RedneckRides) + { + TextItem "ORIGINAL CONCEPT, DESIGN AND DIRECTION\n\nDREW MARKHAM", 80 + TextItem "ART DIRECTION AND ADDITIONAL DESIGN\n\nCORKY LEHMKUHL", 80 + TextItem "PRODUCED BY\n\nGREG GOODRICH", 80 + TextItem "GAME PROGRAMMING\n\nJOSEPH AURILI", 80 + TextItem "ORIGINAL GAME PROGRAMMING\n\nRAFAEL PAIZ", 80 + TextItem "LEVEL DESIGN\n\nRHETT BALDWIN & AARON BARBER", 80 + TextItem "ORIGINAL ART DIRECTION AND SUPPORT\n\nMAXX KAUFMAN & CLAIRE PRADERIE-MARKHAM", 80 + TextItem "COMPUTER GRAPHICS SUPERVISOR &\nCHARACTER ANIMATION DIRECTION\n\nBARRY DEMPSEY", 80 + TextItem "SENIOR ANIMATOR & MODELER\n\nJASON HOOVER", 80 + TextItem "CHARACTER ANIMATION &\nMOTION CAPTURE SPECIALIST\n\nAMIT DORON", 80 + TextItem "SOUND DESIGN &\nMUSIC PRODUCTION COORDINATION\n\nGARY BRADFIELD", 80 + TextItem "INTRODUCTION ANIMATION\n\nDOMINIQUE DROZDZ", 80 + TextItem "ARTIST\n\nMATTHIAS BEEGUER", 80 + TextItem "ADDITIONAL ART\n\nVIKTOR ANTONOV", 80 + TextItem "PRODUCTION COORDINATOR\n\nVICTORIA SYLVESTER", 80 + TextItem "CHARACTER VOICES\n\nLEONARD\nBURTON GILLIAM\n\nDAISY MAE\nTARA CHARENDOFF\n\nBUBBA, BILLY RAY, SKINNY OL' COOT,\nFRANK THE BIKER, THE TURD MINION\n& ALL OTHER VARIOUS RAMBLINGS...\nDREW MARKHAM", 40 + TextItem "SPECIAL APPEARENCE BY\n\nSHERIFF LESTER T. HOBBES\nMOJO NIXON\n\nALIEN VIXEN\nPEGGY JO JACOBS", 70 + TextItem "REDNECK RAMPAGE TITLE TRACK & CYBERSEX\nWRITTEN & PERFORMED BY\nMOJO NIXON\n\n(c) MUFFIN'STUFFIN' MUSIC (BMI)\nADMINISTERED BY BUG.", 70 + TextItem "MUSIC\n\nDISGRACELAND\nTINY D & THE SOFA KINGS\n\nBANJO AND GUITAR PICKIN\nJOHN SCHLOCKER\nHOWARD YEARWOOD", 60 + TextItem "RECORDING ENGINEER\nDAVE AHLERT\n\nRECORDING ASSISTANCE\nJEFF GILBERT", 80 + TextItem "MOTION CAPTURE ACTOR\nJ.P. MANOUX\n\nMOTION CAPTURE ACTRESS\nSHAWN WOLFE", 80 + TextItem "THIS GAME COULD NOT HAVE BEEN MADE WITHOUT\nALEX MAYBERRY\nMAL BLACKWELL\n\nNUTS AND BOLTS\nSTEVE GOLDBERG\n\nBEAN COUNTING\nMAX YOSHIKAWA\n\nADMINISTRATIVE ASSISTANCE\nMINERVA MAYBERRY", 50 + TextItem "FOR INTERPLAY\n\nPRODUCER\nBILL DUGAN\n\nLINE PRODUCER\nCHRIS BENSON\n\nLEAD TESTER\nDARRELL JONES", 60 + TextItem "TESTERS\n\nTIM ANDERSON\nPRIMO PULANCO\nMARK MCCARTY\nBRIAN AXLINE", 70 + TextItem "PRODUCTION BABY\n\nPAULINE MARIE MARKHAM", 80 + TextItem "ORIGINAL PRODUCTION BABY\n\nALYSON KAUFMAN", 80 + TextItem "3D BUILD ENGINE LICENSED FROM\n3D REALMS ENTERTAINMENT\n\nBUILD ENGINE AND RELATED TOOLS\nCREATED BY KEN SILVERMAN", 80 + TextItem "SPECIAL THANKS\n\nSCOTT MILLER\nGEORGE BROUSSARD", 80 + TextItem "EXTRA SPECIAL THANKS\n\nBRIAN FARGO", 80 + TextItem "REDNECK RAMPAGE RIDES AGAIN\n(c) 1998 XATRIX ENTERTAINMENT, INC.\n\nREDNECK RAMPAGE RIDES AGAIN\nIS A TRADEMARK OF\nINTERPLAY PRODUCTIONS", 70 + animatedtransition + } + ifgame(blood) + { + class "Blood.ImageScrollerMenu" + QAVAnimationItem "Credits.qav" + } + ifgame(ShadowWarrior) + { + ifshareware(true) + { + ImageItem "#5110" + ImageItem "#5112" + } + ImageItem "#5111" + ImageItem "#5118" + ImageItem "#4979" + ImageItem "#5113" + } +} + +//------------------------------------------------------------------------------------------- +// +// Base definition for load game menu. Only the configurable part is done here +// +//------------------------------------------------------------------------------------------- + +ListMenu "LoadGameMenu" +{ + Caption "$MNU_LOADGAME" + Position 0, 40 + Class "LoadMenu" // uses its own implementation +} + +//------------------------------------------------------------------------------------------- +// +// Base definition for save game menu. Only the configurable part is done here +// +//------------------------------------------------------------------------------------------- + +ListMenu "SaveGameMenu" +{ + Caption "$MNU_SAVEGAME" + Position 0, 40 + Class "SaveMenu" // uses its own implementation +} + +//------------------------------------------------------------------------------------------- +// +// The generic options menus start here +// +//------------------------------------------------------------------------------------------- + +OptionValue "YesNo" +{ + 0, "$TXT_NO" + 1, "$TXT_YES" +} + +OptionValue "NoYes" +{ + 0, "$TXT_YES" + 1, "$TXT_NO" +} + +OptionValue "OnOff" +{ + 0, "$OPTVAL_OFF" + 1, "$OPTVAL_ON" +} + +OptionValue "OffOn" +{ + 0, "$OPTVAL_ON" + 1, "$OPTVAL_OFF" +} + +OptionValue AutoOffOn +{ + -1, "$OPTVAL_AUTO" + 0, "$OPTVAL_OFF" + 1, "$OPTVAL_ON" +} + +OptionMenuSettings +{ + Linespacing 17 + // todo: implement color themes that fit the games +} + +DefaultOptionMenu +{ + Position 85 +} + +OptionMenu "OptionsMenu" +{ + Caption "$MNU_OPTIONS" + Submenu "$OPTMNU_CONTROLS", "CustomizeControls" + Submenu "$OPTMNU_MOUSE", "MouseOptions" + Submenu "$OPTMNU_JOYSTICK", "JoystickOptions" + StaticText " " + Submenu "$OPTMNU_PLAYER", "NewPlayerMenu" + Submenu "$OPTMNU_SOUND", "SoundOptions" + Submenu "$OPTMNU_DISPLAY", "VideoOptions" + Submenu "$OPTMNU_VIDEO", "VideoModeMenu" + Submenu "$OPTMNU_GAMEPLAY", "GameplayOptions" + Submenu "$OPTMNU_MISCELLANEOUS", "MiscOptions" + StaticText " " + SafeCommand "$OPTMNU_DEFAULTS", "reset2defaults" + SafeCommand "$OPTMNU_RESETTOSAVED", "reset2saved" + Command "$OPTMNU_CONSOLE", "menuconsole" +} + +//------------------------------------------------------------------------------------------- +// +// Controls Menu +// +//------------------------------------------------------------------------------------------- + +OptionMenu "CustomizeControls"// protected +{ + Title "$CNTRLMNU_TITLE" + + Submenu "$CNTRLMNU_ACTION" , "ActionControlsMenu" + Submenu "$CNTRLMNU_CHAT" , "ChatControlsMenu" + Submenu "$CNTRLMNU_WEAPONS" , "WeaponsControlMenu" + Submenu "$CNTRLMNU_INVENTORY" , "InventoryControlsMenu" + Submenu "$CNTRLMNU_OTHER" , "OtherControlsMenu" + //Submenu "$MAPCNTRLMNU_CONTROLS" , "MapControlsMenu" // todo after thorough cleanup +} + +OptionMenu "ActionControlsMenu"// protected +{ + Title "$CNTRLMNU_ACTION_TITLE" + ScrollTop 2 + StaticTextSwitchable "$CNTRLMNU_SWITCHTEXT1", "$CNTRLMNU_SWITCHTEXT2", "ControlMessage" + + StaticText "" + Control "$CNTRLMNU_ATTACK" , "+fire" + ifgame(Blood, Duke, Nam, WW2GI, Fury) + { + Control "$CNTRLMNU_ALTATTACK" , "+alt_fire" + } + ifgame(Duke, Nam, WW2GI, Fury, ShadowWarrior) + { + Control "$CNTRLMNU_ALTWEAPON" , "+alt_weapon" + } + + StaticText "" + Control "$CNTRLMNU_USE" , "+open" + + StaticText "" + Control "$CNTRLMNU_FORWARD" , "+move_forward" + Control "$CNTRLMNU_BACK" , "+move_backward" + Control "$CNTRLMNU_MOVELEFT" , "+strafe_left" + Control "$CNTRLMNU_MOVERIGHT" , "+strafe_right" + + StaticText "" + Control "$CNTRLMNU_TURNLEFT" , "+turn_left" + Control "$CNTRLMNU_TURNRIGHT" , "+turn_right" + Control "$CNTRLMNU_TURN180" , "+turn_around" + + StaticText "" + Control "$CNTRLMNU_JUMP" , "+jump" + Control "$CNTRLMNU_CROUCH" , "+crouch" + ifgame(Duke, Nam, WW2GI, Fury, Redneck, RedneckRides) + { + // Fixme: Make this work in all games + Control "$CNTRLMNU_TOGGLECROUCH" , "+toggle_crouch" + } + + StaticText "" + Control "$CNTRLMNU_MOUSELOOK" , "+mouse_aiming" + Control "$CNTRLMNU_MLOOKTOGGLE" , "togglemouseaim" + + Control "$CNTRLMNU_AIMUP" , "+aim_up" + Control "$CNTRLMNU_AIMDOWN" , "+aim_down" + Control "$CNTRLMNU_LOOKUP" , "+look_up" + Control "$CNTRLMNU_LOOKDOWN" , "+look_down" + ifgame(Duke, Nam, WW2GI, Fury, Redneck, RedneckRides) + { + Control "$CNTRLMNU_LOOKLEFT" , "+look_left" + Control "$CNTRLMNU_LOOKRIGHT" , "+look_right" + } + Control "$CNTRLMNU_CENTERVIEW" , "+center_view" + + StaticText "" + Control "$CNTRLMNU_RUN" , "+run" + Control "$CNTRLMNU_TOGGLERUN" , "toggle cl_autorun" + Control "$CNTRLMNU_STRAFE" , "+strafe" + + StaticText "" + Control "$CNTRLMNU_SCOREBOARD" , "+show_dukematch_scores" +} + +OptionMenu "ChatControlsMenu"// protected +{ + Title "$CNTRLMNU_CHAT_TITLE" + ScrollTop 2 + StaticTextSwitchable "$CNTRLMNU_SWITCHTEXT1", "$CNTRLMNU_SWITCHTEXT2", "ControlMessage" + + StaticText "" + Control "$CNTRLMNU_SAY" , "+send_message" +} + +OptionMenu "WeaponsControlMenu"// protected +{ + Title "$CNTRLMNU_WEAPONS_TITLE" + ScrollTop 2 + StaticTextSwitchable "$CNTRLMNU_SWITCHTEXT1", "$CNTRLMNU_SWITCHTEXT2", "ControlMessage" + + StaticText "" + Control "$CNTRLMNU_NEXTWEAPON" , "+next_weapon" + Control "$CNTRLMNU_PREVIOUSWEAPON" , "+previous_weapon" + + StaticText "" + Control "$CNTRLMNU_SLOT1" , "+weapon_1" + Control "$CNTRLMNU_SLOT2" , "+weapon_2" + Control "$CNTRLMNU_SLOT3" , "+weapon_3" + Control "$CNTRLMNU_SLOT4" , "+weapon_4" + Control "$CNTRLMNU_SLOT5" , "+weapon_5" + Control "$CNTRLMNU_SLOT6" , "+weapon_6" + Control "$CNTRLMNU_SLOT7" , "+weapon_7" + Control "$CNTRLMNU_SLOT8" , "+weapon_8" + Control "$CNTRLMNU_SLOT9" , "+weapon_9" + Control "$CNTRLMNU_SLOT0" , "+weapon_10" + StaticText "" + Control "$CNTRLMNU_HOLSTER" , "+holster_weapon" + ifgame(Fury) + { + Control "$CNTRLMNU_RELOAD" , "+steroids" + } + ifgame(Duke, Nam, WW2GI, Fury) + { + Control "$CNTRLMNU_QUICKKICK" , "+quick_kick" + } + + ifgame(Redneck, RedneckRides) + { + Control "$CNTRLMNU_PEE" , "+quick_kick" + } + ifgame(Blood) + { + Control "$CNTRLMNU_PROXIMITYBOMBS","+proximitybombs" + Control "$CNTRLMNU_REMOTEBOMBS" ,"+remotebombs" + } + ifgame(ShadowWarrior) + { + Control "$CNTRLMNU_SMOKEBOMB","+smoke_bomb" + Control "$CNTRLMNU_GASBOMB" ,"+gas_bomb" + Control "$CNTRLMNU_FLASHBOMB","+flash_bomb" + Control "$CNTRLMNU_CALTROPS" ,"+caltrops" + } + +} + +OptionMenu "InventoryControlsMenu"// protected +{ + Title "$CNTRLMNU_INVENTORY_TITLE" + ScrollTop 2 + StaticTextSwitchable "$CNTRLMNU_SWITCHTEXT1", "$CNTRLMNU_SWITCHTEXT2", "ControlMessage" + + StaticText "" + Control "$CNTRLMNU_USEITEM" , "+inventory" + + StaticText "" + Control "$CNTRLMNU_NEXTITEM" , "+inventory_right" + Control "$CNTRLMNU_PREVIOUSITEM" , "+inventory_left" + + ifgame(Duke) + { + StaticText "" + Control "$CNTRLMNU_HOLODUKE" , "+holo_duke" + Control "$CNTRLMNU_JETPACK" , "+jetpack" + Control "$CNTRLMNU_NIGHTVISION" , "+nightvision" + Control "$CNTRLMNU_MEDKIT" , "+medkit" + Control "$CNTRLMNU_STEROIDS" , "+steroids" + } + ifgame(Fury) + { + StaticText "" + Control "$CNTRLMNU_RADAR" , "+nightvision" + Control "$CNTRLMNU_MEDKIT" , "+medkit" + } + ifgame(Nam) + { + StaticText "" + Control "$CNTRLMNU_HOLOSOLDIER" , "+holo_duke" + Control "$CNTRLMNU_HUEY" , "+jetpack" + Control "$CNTRLMNU_NIGHTVISION" , "+nightvision" + Control "$CNTRLMNU_MEDKIT" , "+medkit" + Control "$CNTRLMNU_TANKMODE" , "+steroids" + } + ifgame(WW2GI) + { + StaticText "" + Control "$CNTRLMNU_FIRE MISSION" , "+holo_duke" + Control "$CNTRLMNU_NIGHTVISION" , "+nightvision" + Control "$CNTRLMNU_MEDKIT" , "+medkit" + Control "$CNTRLMNU_SMOKES" , "+steroids" + } + ifgame(Redneck, RedneckRides) + { + StaticText "" + Control "$CNTRLMNU_BEER" , "+holo_duke" + Control "$CNTRLMNU_COWPIE" , "+jetpack" + Control "$CNTRLMNU_YEEHAA" , "+nightvision" + Control "$CNTRLMNU_WHISKEY" , "+medkit" + Control "$CNTRLMNU_MOONSHINE" , "+steroids" + } + ifgame(Blood) + { + StaticText "" + Control "$CNTRLMNU_CRYSTALBALL" , "+crystalball" + Control "$CNTRLMNU_JUMPBOOTS" , "+jetpack" + Control "$CNTRLMNU_BEASTVISION" , "+nightvision" + Control "$CNTRLMNU_MEDKIT" , "+medkit" + } + ifgame(ShadowWarrior) + { + StaticText "" + Control "$CNTRLMNU_NIGHTVISION" , "+nightvision" + Control "$CNTRLMNU_MEDKIT" , "+medkit" + } +} + +OptionMenu "OtherControlsMenu"// protected +{ + Title "$CNTRLMNU_OTHER_TITLE" + ScrollTop 2 + StaticTextSwitchable "$CNTRLMNU_SWITCHTEXT1", "$CNTRLMNU_SWITCHTEXT2", "ControlMessage" + + StaticText "" + Control "$CNTRLMNU_AUTOMAP" , "+map" + Control "$MAPCNTRLMNU_TOGGLEFOLLOW","+map_follow_mode" + + StaticText "" + Control "$CNTRLMNU_CHASECAM" , "+third_person_view" + + StaticText "" + Control "$CNTRLMNU_SCREENSHOT" , "screenshot" + Control "$CNTRLMNU_CONSOLE" , "toggleconsole" + Control "$CNTRLMNU_PAUSE" , "pause" + + StaticText "" + Control "$CNTRLMNU_DISPLAY_INC" , "+enlarge_Screen" + Control "$CNTRLMNU_DISPLAY_DEC" , "+shrink_screen" + Control "$CNTRLMNU_TOGGLE_MESSAGES" , "togglemessages" + Control "$CNTRLMNU_ADJUST_GAMMA" , "bumpgamma" + + StaticText "" + Control "$CNTRLMNU_OPEN_HELP" , "openhelpmenu" + Control "$CNTRLMNU_OPEN_SAVE" , "opensavemenu" + Control "$CNTRLMNU_OPEN_LOAD" , "openloadmenu" + Control "$CNTRLMNU_OPEN_OPTIONS" , "openmenu optionsmenu" + Control "$CNTRLMNU_OPEN_DISPLAY" , "openmenu displayoptions" + Control "$CNTRLMNU_EXIT_TO_MAIN" , "menu_endgame" + Control "$CNTRLMNU_MENU_QUIT" , "menu_quit" + + StaticText "" + Control "$CNTRLMNU_QUICKSAVE" , "quicksave" + Control "$CNTRLMNU_QUICKLOAD" , "quickload" +} + +//------------------------------------------------------------------------------------------- +// +// Mouse Menu +// +//------------------------------------------------------------------------------------------- + +OptionValue "Corners" +{ + -1, "$OPTVAL_OFF" + 0, "$OPTVAL_UPPERLEFT" + 1, "$OPTVAL_UPPERRIGHT" + 2, "$OPTVAL_LOWERLEFT" + 3, "$OPTVAL_LOWERRIGHT" +} + +OptionValue "MenuMouse" +{ + 0, "$TXT_NO" + 1, "$TXT_YES" + 2, "$OPTVAL_TOUCHSCREENLIKE" +} + +OptionString "Cursors" +{ + "None", "$OPTVAL_DEFAULT" + "cursor", "$OPTSTR_SIMPLEARROW" + "-", "$OPTSTR_SYSTEMCURSOR" +} + +OptionMenu "MouseOptions" //protected +{ + Title "$MOUSEMNU_TITLE" + Option "$MOUSEMNU_ENABLEMOUSE", "in_mouse", "YesNo" + Option "$MOUSEMNU_MOUSEINMENU", "m_use_mouse", "MenuMouse", "use_mouse" + Option "$MOUSEMNU_SHOWBACKBUTTON", "m_show_backbutton", "Corners", "use_mouse" + // todo Option "$MOUSEMNU_CURSOR", "vid_cursor", "Cursors" + StaticText "" + Slider "$MOUSEMNU_SENSITIVITY", "mouse_sensitivity", 0.5, 2.5, 0.1 + Option "$MOUSEMNU_NOPRESCALE", "m_noprescale", "NoYes" + Option "$MOUSEMNU_SMOOTHMOUSE", "in_mousesmoothing", "YesNo" + StaticText "" + Slider "$MOUSEMNU_TURNSPEED", "in_mousescalex", -4, 4, 0.2 + Slider "$MOUSEMNU_MOUSELOOKSPEED", "in_mousescaley", -4, 4, 0.2 + //Slider "$MOUSEMNU_FORWBACKSPEED", "in_mouseforward", 0, 2.5, 0.1 + //Slider "$MOUSEMNU_STRAFESPEED", "in_mouseside", 0, 2.5, 0.1 + StaticText "" + Option "$MOUSEMNU_ALWAYSMOUSELOOK", "in_mousemode", "OnOff" + Option "$MOUSEMNU_INVERTMOUSE", "in_mouseflip", "OnOff" + // Do we need this? Option "$MOUSEMNU_LOOKSTRAFE", "lookstrafe", "OnOff" +} + +//------------------------------------------------------------------------------------------- +// +// Joystick Menu +// +//------------------------------------------------------------------------------------------- + +OptionMenu "JoystickOptions"//Defaults" //protected +{ + Title "$JOYMNU_OPTIONS" + Option "$JOYMNU_ENABLE", "use_joystick", "YesNo" + Option "$JOYMNU_NOMENU", "m_blockcontrollers", "YesNo" + /*IfOption(Windows) + { + Option "$JOYMNU_DINPUT", "joy_dinput", "YesNo" + Option "$JOYMNU_XINPUT", "joy_xinput", "YesNo" + Option "$JOYMNU_PS2", "joy_ps2raw", "YesNo" + }*/ + StaticText "" + StaticTextSwitchable "$JOYMNU_NOCON", "$JOYMNU_CONFIG", "ConfigureMessage" + StaticTextSwitchable " ", "$JOYMNU_DISABLED1", "ConnectMessage1" + StaticTextSwitchable " ", "$JOYMNU_DISABLED2", "ConnectMessage2" + + // The rest will be filled in by joystick code if devices get connected or disconnected +} + +OptionMenu "JoystickOptions1" //protected +{ + Title "$JOYMNU_OPTIONS" +} + +OptionValue "JoyAxisMapNames" +{ + -1, "$OPTVAL_NONE" + 0, "$OPTVAL_TURNING" + 1, "$OPTVAL_LOOKINGUPDOWN" + 2, "$OPTVAL_MOVINGFORWARD" + 3, "$OPTVAL_STRAFING" + 4, "$OPTVAL_MOVINGUPDOWN" +} + +OptionValue "Inversion" +{ + 0, "$OPTVAL_NOTINVERTED" + 1, "$OPTVAL_INVERTED" +} + +OptionMenu "JoystickConfigMenu" //protected +{ + Title "$JOYMNU_TITLE" + Class "JoystickConfigMenu" + // Will be filled in by joystick code. +} + + +OptionValue "PlayerColors" +{ + 0, "$OPTVAL_AUTO" + 1, "$TXT_COLOR_BLUE" + 2, "$TXT_COLOR_RED" + 3, "$TXT_COLOR_GREEN" + 4, "$TXT_COLOR_GRAY" + 5, "$TXT_COLOR_DARKGRAY" + 6, "$TXT_COLOR_DARKGREEN" + 7, "$TXT_COLOR_BROWN" + 8, "$TXT_COLOR_DARKBLUE" + 9, "$TXT_COLOR_LIGHTRED" + //10, "$TXT_COLOR_YELLOW" +} + +OptionValue "PlayerColorsSW" +{ + 0, "$TXT_COLOR_BROWN" + 1, "$TXT_COLOR_GRAY" + 2, "$TXT_COLOR_PURPLE" + 3, "$TXT_COLOR_RED" + 4, "$TXT_COLOR_YELLOW" + 5, "$TXT_COLOR_DULLGREEN" + 6, "$TXT_COLOR_GREEN" + 7, "$TXT_COLOR_BLUE" +} + +OptionValue "PlayerTeam" +{ + 0, "$TXT_COLOR_BLUE" + 1, "TXT_COLOR_RED" + 2, "TXT_COLOR_GREEN" + 3, "TXT_COLOR_GRAY" +} + +OptionValue "Gender" +{ + 0, "$OPTVAL_MALE" + 1, "$OPTVAL_FEMALE" + 2, "$OPTVAL_NEUTRAL" + 3, "$OPTVAL_OTHER" +} + + +OptionMenu "NewPlayerMenu" //protected +{ + Title "$MNU_PLAYERSETUP" + TextField "$PLYRMNU_NAME", playername + ifgame(Duke, Nam, WW2GI, Fury, Redneck, RedneckRides) + { + Option "$PLYRMNU_PLAYERCOLOR", "playercolor", "PlayerColors" + } + ifgame(ShadowWarrior) + { + // This curently does not get applied to the single player game. + Option "$PLYRMNU_PLAYERCOLOR", "playercolor", "PlayerColorsSW" + } + Option "$PLYRMNU_PLAYERGENDER", "playergender", "Gender" + Option "$PLYRMNU_TEAM", "playerteam", "PlayerTeam" + Submenu "$PLRMNU_TAUNTS", "TauntsMenu" + Class "NewPlayerMenu" +} + +OptionMenu "TauntsMenu" //protected +{ + Title "$PLRMNU_TAUNTS" + TextField "1", "combatmacro0" + TextField "2", "combatmacro1" + TextField "3", "combatmacro2" + TextField "4", "combatmacro3" + TextField "5", "combatmacro4" + TextField "6", "combatmacro5" + TextField "7", "combatmacro6" + TextField "8", "combatmacro7" + TextField "9", "combatmacro8" + TextField "10", "combatmacro9" +} + +//------------------------------------------------------------------------------------------- +// +// Game Setup +// +//------------------------------------------------------------------------------------------- + +OptionValue "AimMode" +{ + 0, "$OPTVAL_NEVER" + 1, "$OPTVAL_ALWAYS" + 2, "$OPTRAL_HITSCAN" +} + +OptionValue "RunMode" +{ + 0, "$PLRMNU_TOGGLE" + 1, "$PLRMNU_OVERRIDE" +} + +OptionValue "WeapSwitch" +{ + 0, "$OPTVAL_NEVER" + 1, "$PLRMNU_IFNEW" + 3, "$PLRMNU_PREFERRED" +} + + +OptionMenu GameplayOptions //protected +{ + Title "$GMPLYMNU_TITLE" + Option "$PLRMNU_AUTOAIM", "cl_autoaim", "AimMode" + Option "$PLRMNU_ALWAYSRUN", "cl_autorun", "OnOff" + Option "$PLRMNU_RUNMODE", "cl_runmode", "RunMode" + ifgame(ShadowWarrior) + { + Option "$PLRMNU_EQUIP", "cl_weaponswitch", "OnOff" // does not have the 'preferred' option. + } + else + { + Option "$PLRMNU_EQUIP", "cl_weaponswitch", "WeapSwitch" + } + Option "$PLRMNU_PLOCK", "adult_lockout", "OnOff" // I won't bother password protecting this piece of window dressing + // StaticText "" + // Option "Record Demo", "m_recstat", "OnOff" + // Submenu "Cheats" "CheatsMenu +} + +//------------------------------------------------------------------------------------------- +// +// Display options +// +//------------------------------------------------------------------------------------------- + +OptionValue "FilterModes" +{ + 0, "$OPTVAL_NONE" + 2, "$OPTVAL_NONENEARESTMIPMAP" + 4, "$OPTVAL_NONELINEARMIPMAP" + 6, "$OPTVAL_NONETRILINEAR" + 3, "$OPTVAL_LINEAR_2" + 1, "$OPTVAL_BILINEAR" + 5, "$OPTVAL_TRILINEAR" +} + +OptionValue "Anisotropy" +{ + 1, "$OPTVAL_OFF" + 2, "$OPTVAL_2X" + 4, "$OPTVAL_4X" + 8, "$OPTVAL_8X" + 16, "$OPTVAL_16X" +} + +OptionMenu "VideoOptions" //protected +{ + Title "$DSPLYMNU_TITLE" + + Submenu "$OPTMNU_HUD", "HUDOptions" + Submenu "$OPTMNU_POLYMOST", "PolymostOptions" + + Slider "$DSPLYMNU_GAMMA", "vid_gamma", 0.75, 3.0, 0.05, 2 + Slider "$DSPLYMNU_BRIGHTNESS", "vid_brightness", -0.8,0.8, 0.05,2 + Slider "$DSPLYMNU_CONTRAST", "vid_contrast", 0.1, 3.0, 0.1 + Slider "$DSPLYMNU_SATURATION", "vid_saturation", -3.0, 3.0, 0.25, 2 + + StaticText "" + Option "$DSPLYMNU_VOXELS", "r_voxels", "OnOff" + StaticText "" + Slider "$DSPLYMNU_FOV", "r_fov", 60, 130, 10, 1 + + StaticText "" + Option "$GLTEXMNU_TEXFILTER", hw_texfilter, "FilterModes" + Option "$GLTEXMNU_ANISOTROPIC", hw_anisotropy, "Anisotropy" +} + + +//------------------------------------------------------------------------------------------- +// +// HUD options +// +//------------------------------------------------------------------------------------------- + +OptionValue "HUDMessages" +{ + 0, "$OPTVAL_OFF" + 1, "$OPTVAL_ON" + 2, "$DSPLYMNU_GENERIC" +} + +OptionMenu "HUDOptions" //protected +{ + Title "$OPTMNU_HUD" + + Slider "$DSPLYMNU_SCREENSIZE", "hud_size", 0.0, 11.0, 1.0, -1 + ifgame(duke, nam, ww2gi, redneck, redneckrides, fury) // Fixme: The scaling really needs to be taken out of the game code. + { + Slider "$DSPLYMNU_SBSCALE", "hud_scale", 0.3, 1.0, 0.1, 2 + } + Option "$DSPLYMNU_LEVELSTATS", "hud_stats", "OnOff" + ifgame(duke, nam, ww2gi, redneck, redneckrides, fury) + { + Slider "$DSPLYMNU_TEXTSCALE", "hud_textscale", 0.3, 1.0, 0.1, 2 + } + StaticText "" + Option "$DSPLYMNU_MESSAGES", "hud_messages", "HudMessages" + StaticText "" + Option "$DSPLYMNU_CROSSHAIR", "cl_crosshair", OnOff + Slider "$DSPLYMNU_CROSSHAIRSCALE", "cl_crosshairscale", 50, 100, 10, 1 +} + + +//------------------------------------------------------------------------------------------- +// +// Polymost options +// +//------------------------------------------------------------------------------------------- + +OptionMenu "PolymostOptions" +{ + Title "Polympost Options" + Option "$POLYMOST_TC", "hw_hightile", "OnOff" + Option "$POLYMOST_CACHE", "r_precache", "OnOff" + StaticText "" + Option "$POLYMOST_DETAIL", "hw_detailmapping", "OnOff", "hw_hightile" + Option "$POLYMOST_GLOW", "hw_glowmapping", "OnOff", "hw_hightile" + StaticText "" + Option "$POLYMOST_PALETTEEMU", "hw_useindexedcolortextures", "OnOff" + Option "$POLYMOST_PALINTER", "hw_shadeinterpolate", "OnOff", "hw_useindexedcolortextures" + StaticText "" + Option "$POLYMOST_MODELS", "hw_models", "OnOff" +} + +//------------------------------------------------------------------------------------------- +// +// Sound options +// Many of these options are not active, but will be needed should I manage to transition +// the entire sound system to OpenAL 3D. So it is easier to just copy all this verbatim +// and only disable the options not yet usable instead of deleting the content. +// +//------------------------------------------------------------------------------------------- + +OptionValue SampleRates +{ + //0, "$OPTVAL_DEFAULT" + //4000, "$OPTVAL_4000HZ" + //8000, "$OPTVAL_8000HZ" + 11025, "$OPTVAL_11025HZ" + 22050, "$OPTVAL_22050HZ" + 32000, "$OPTVAL_32000HZ" + 44100, "$OPTVAL_44100HZ" + 48000, "$OPTVAL_48000HZ" +} + + +OptionValue BufferSizes +{ + 0, "$OPTVAL_DEFAULT" + 64, "$OPTVAL_64SAMPLES" + 128, "$OPTVAL_128SAMPLES" + 256, "$OPTVAL_256SAMPLES" + 512, "$OPTVAL_512SAMPLES" + 1024, "$OPTVAL_1024SAMPLES" + 2048, "$OPTVAL_2048SAMPLES" + 4096, "$OPTVAL_4096SAMPLES" +} + +OptionString ALDevices +{ + // filled in by the sound code +} + +OptionString ALResamplers +{ + // filled in by the sound code +} + +OptionString SpeakerModes +{ + "Auto", "$OPTSTR_AUTO" + "Mono", "$OPTSTR_MONO" + "Stereo", "$OPTSTR_STEREO" + "Prologic", "$OPTSTR_PROLOGIC" + "Quad", "$OPTSTR_QUAD" + "Surround", "$OPTSTR_SURROUND" + "5.1", "$OPTSTR_5POINT1" + "7.1", "$OPTSTR_7POINT1" +} + + +OptionMenu OpenALSoundItems //protected +{ + Title "$OPENALMNU_TITLE" + Option "$OPENALMNU_PLAYBACKDEVICE", "snd_aldevice", "ALDevices" + Option "$OPENALMNU_ENABLEEFX", "snd_efx", "OnOff" + Option "$OPENALMNU_RESAMPLER", "snd_alresampler", "ALResamplers" +} + + +OptionValue MidiDevices +{ + // filled in by the sound code +} + +OptionMenu SoundOptions //protected +{ + Title "$SNDMNU_TITLE" + Slider "$MODMNU_MASTERVOLUME", "snd_mastervolume", 0, 1, 0.05, 2 + StaticText " " + Option "$SNDMNU_SNDENABLED", "snd_enabled", "YesNo" + Slider "$SNDMNU_SFXVOLUME", "snd_fxvolume", 0, 255, 2, 1 + //Slider "$SNDMNU_SFXVOLUME", "snd_sfxvolume", 0, 1, 0.05, 2 // Todo: Change value type + Option "$SNDMNU_MUSENABLED", "mus_enabled", "YesNo" + Slider "$SNDMNU_MUSICVOLUME", "mus_volume", 0, 1, 0.05, 2 + Option "$SNDMNU_MENUSOUND", "menu_sounds", "OnOff" // placeholder until the slider can be made to work + //Slider "$SNDMNU_MENUVOLUME", "snd_menuvolume", 0, 1, 0.05, 2 + StaticText " " + Option "$SNDMNU_MIDIDEVICE", "snd_mididevice", "MidiDevices" + StaticText " " + //Option "$SNDMNU_UNDERWATERREVERB", "snd_waterreverb", "OnOff" + //Option "$SNDMNU_RANDOMIZEPITCHES", "snd_pitched", "OnOff" + Slider "$SNDMNU_CHANNELS", "snd_numchannels", 64, 128, 8, 0 + staticText "" + ifgame (Blood, ShadowWarrior, Redneck, RedneckRides) + { + Option "$SNDMNU_CDEMU", "mus_redbook", "OnOff" + } + ifgame(Duke, Nam, WW2GI, Fury, Redneck, RedneckRides, ShadowWarrior) + { + Option "$SNDMNU_AMBIENCE", "snd_ambience", "OnOff" + Option "$SNDMNU_SPEECH", "snd_speech", "OnOff" + } + StaticText " " + Submenu "$SNDMNU_ADVANCED", "AdvSoundOptions" +} + +/*======================================= + * + * Advanced Sound Options Menu + * + *=======================================*/ + +OptionValue OplCores +{ + 0, "$OPTVAL_MAMEOPL2" + 1, "$OPTVAL_DOSBOXOPL3" + 2, "$OPTVAL_JAVAOPL3" + 3, "$OPTVAL_NUKEDOPL3" +} + + +OptionMenu AdvSoundOptions //protected +{ + Title "$ADVSNDMNU_TITLE" + Option "$ADVSNDMNU_SAMPLERATE", "snd_mixrate", "SampleRates" + //Option "$ADVSNDMNU_HRTF", "snd_hrtf", "AutoOffOn" + Option "$ADVSNDMNU_FLIPSTEREO", "snd_reversestereo", "OnOff" + StaticText " " + //Option "$SNDMNU_BACKGROUND", "i_soundinbackground", "OnOff" + //StaticText " " + + ifoption(openal) + { + StaticText " " + Submenu "$SNDMNU_OPENAL", "OpenALSoundItems" + } + + StaticText " " + Submenu "$SNDMNU_MIDIPLAYER", "MidiPlayerOptions" + Submenu "$SNDMNU_MODREPLAYER", "ModReplayerOptions" + StaticText " " + Command "$SNDMNU_RESTART", "restartsound" +} + + +OptionMenu TimidityConfigMenu //protected +{ + Title "$ADVSNDMNU_SELCONFIG" +} + +OptionMenu FluidPatchsetMenu //protected +{ + Title "$ADVSNDMNU_SELCONFIG" +} + +/*======================================= + * + * Module Replayer Options Menu + * + *=======================================*/ + +OptionValue ModQuality +{ + 0.0, "$OPTVAL_ALIASING" + 1.0, "$OPTVAL_LINEAR_1" + 2.0, "$OPTVAL_CUBIC" + 3.0, "$OPTVAL_BLEP" // Band-limited step + 4.0, "$OPTVAL_LINEARSLOW" + 5.0, "$OPTVAL_BLAM" // Band-limited linear + 6.0, "$OPTVAL_CUBICSLOW" + 7.0, "$OPTVAL_SINC" +} + + +OptionValue ModVolumeRamps +{ + 0.0, "$OPTVAL_NONE" + 1.0, "$OPTVAL_NOTEONOFFONLY" + 2.0, "$OPTVAL_FULLRAMPING" +} + + + +OptionMenu ModReplayerOptions //protected +{ + Title "$MODMNU_TITLE" + Slider "$MODMNU_MASTERVOLUME", "mod_dumb_mastervolume", 1, 16, 0.5, 1 + Option "$ADVSNDMNU_SAMPLERATE", "mod_samplerate", "SampleRates" + Option "$MODMNU_QUALITY", "mod_interp", "ModQuality" + Option "$MODMNU_VOLUMERAMPING", "mod_volramp", "ModVolumeRamps" + StaticText " " + Option "$MODMNU_CHIPOMATIC", "mod_autochip", "OnOff" + // TODO if the menu system is ever rewritten: Provide a decent + // mechanism to edit the chip-o-matic settings like you can with + // the foo_dumb preferences in foobar2000. +} + +/*======================================= + * + * MIDI player + * + *=======================================*/ + + OptionValue TimidityReverb + { + 0, "$OPTVAL_OFF" + 1, "$OPTVAL_STANDARD" + 2, "$ADVSNDMNU_GLOBAL" + 3, "$ADVSNDMNU_FREEVERB" + 4, "$ADVSNDMNU_GLOBAL_FREEVERB" + } + + OptionMenu MidiPlayerOptions //protected + { + Title "$SNDMNU_MIDIPLAYER" + Submenu "$ADVSNDMNU_FLUIDSYNTH", "FluidsynthOptions"//, 0, 1 + Submenu "$ADVSNDMNU_TIMIDITY", "TimidityOptions"//, 0, 1 + Submenu "$ADVSNDMNU_OPLSYNTHESIS", "OPLOptions"//, 0, 1 + } + + OptionMenu FluidsynthOptions //protected + { + Title "$ADVSNDMNU_FLUIDSYNTH" + LabeledSubMenu "$ADVSNDMNU_SELCONFIG", "fluid_patchset", "FluidPatchsetMenu" + Slider "$ADVSNDMNU_FLUIDGAIN", "fluid_gain", 0, 10, 0.5, 1 + Option "$ADVSNDMNU_REVERB", "fluid_reverb", "OnOff" + Option "$ADVSNDMNU_CHORUS", "fluid_chorus", "OnOff" + Slider "$ADVSNDMNU_MIDIVOICES", "fluid_voices", 16, 4096, 16, 0 + // other CVARs need to be revieved for usefulness + } + + OptionMenu TimidityOptions //protected + { + Title "$ADVSNDMNU_TIMIDITY" + LabeledSubMenu "$ADVSNDMNU_SELCONFIG", "timidity_config", "TimidityConfigMenu" + Option "$ADVSNDMNU_REVERB", "timidity_reverb", "TimidityReverb" + Slider "$ADVSNDMNU_REVERB_LEVEL", "timidity_reverb_level", 9, 127, 1, 0 + Option "$ADVSNDMNU_CHORUS", "timidity_chorus", "OnOff" + // other CVARs need to be revieved for usefulness + } + + OptionMenu OPLOptions //protected + { + Title "$ADVSNDMNU_OPLSYNTHESIS" + Option "$ADVSNDMNU_OPLCORES", "opl_core", "OplCores" + Slider "$ADVSNDMNU_OPLNUMCHIPS", "opl_numchips", 1, 8, 1, 0 + Option "$ADVSNDMNU_OPLFULLPAN", "opl_fullpan", "OnOff" + } + +/*======================================= + * + * Video mode menu + * Even more than the sound, much of this has no backing + * and needs replacement of the backend. + * + *=======================================*/ + +OptionValue ForceRatios +{ + 0.0, "$OPTVAL_OFF" + 3.0, "4:3" + 1.0, "16:9" + 5.0, "17:10" + 2.0, "16:10" + 4.0, "5:4" + 6.0, "21:9" +} +OptionValue Ratios +{ + 0.0, "4:3" + 4.0, "5:4" + 1.0, "16:9" + 2.0, "16:10" + 3.0, "17:10" + 6.0, "21:9" + -1, "$OPTVAL_ALL" +} +OptionValue ScaleModes +{ + 0, "$OPTVAL_SCALENEAREST" + 1, "$OPTVAL_SCALELINEAR" + 2, "640x400" + 3, "960x600" + 4, "1280x800" + 5, "$OPTVAL_CUSTOM" +} +OptionValue CropAspect +{ + 0, "$OPTVAL_STRETCH" + 1, "$OPTVAL_LETTERBOX" +} + +OptionValue MaxFps +{ + 0, "$OPTVAL_UNLIMITED" + 60, "$OPTVAL_60FPS" + 75, "$OPTVAL_75FPS" + 90, "$OPTVAL_90FPS" + 120, "$OPTVAL_120FPS" + 144, "$OPTVAL_144FPS" + 200, "$OPTVAL_200FPS" +} + +OptionMenu VideoModeMenu //protected +{ + Title "$VIDMNU_TITLE" + + StaticText "Caution: This menu is currently" + StaticText "not functional!" + + Option "$VIDMNU_RENDERMODE", "vid_rendermode", "RenderMode" + Option "$VIDMNU_FULLSCREEN", "fullscreen", "YesNo" + + IfOption(Mac) + { + Option "$VIDMNU_HIDPI", "vid_hidpi", "YesNo" + } + IfOption(Windows) + { + Option "$DSPLYMNU_GPUSWITCH", vid_gpuswitch, "GPUSwitch" + } + + Option "$VIDMNU_FORCEASPECT", "vid_aspect", "ForceRatios" + Option "$VIDMNU_CROPASPECT", "vid_cropaspect", "CropAspect" + Option "$VIDMNU_SCALEMODE", "vid_scalemode", "ScaleModes" + Slider "$VIDMNU_SCALEFACTOR", "vid_scalefactor", 0.25, 2.0, 0.25, 2 + + StaticText " " + Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff" + Option "$VIDMNU_MAXFPS", "r_maxfps", "MaxFps" + + StaticText "" + StaticText "$VIDMNU_CUSTOMRES" + TextField "$VIDMNU_CUSTOMX", menu_resolution_custom_width + TextField "$VIDMNU_CUSTOMY", menu_resolution_custom_height + Option "$VIDMNU_USELINEAR", "vid_scale_customlinear", "YesNo" + StaticText "" + Command "$VIDMNU_APPLYW", "menu_resolution_commit_changes 0" + Command "$VIDMNU_APPLYFS", "menu_resolution_commit_changes 1" + StaticText "" + + SubMenu "$VIDMNU_RESPRESET", CustomResolutionMenu +} + +OptionMenu CustomResolutionMenu //protected +{ + Title "$VIDMNU_RESPRESETTTL" + + StaticText "$VIDMNU_RESPRESETHEAD" + StaticText "" + StaticText "$VIDMNU_ASPECT43" + Command "640x480", "menu_resolution_set_custom 640 480" + Command "1024x768", "menu_resolution_set_custom 1024 768" + Command "1280x960", "menu_resolution_set_custom 1280 960" + Command "1600x1200", "menu_resolution_set_custom 1600 1200" + StaticText "" + StaticText "$VIDMNU_ASPECT54" + Command "1280x1024", "menu_resolution_set_custom 1280 1024" + StaticText "" + StaticText "$VIDMNU_ASPECT169" + Command "960x540", "menu_resolution_set_custom 960 540" + Command "(720p HD) 1280x720", "menu_resolution_set_custom 1280 720" + Command "1366x768", "menu_resolution_set_custom 1366 768" + Command "(1080p HD) 1920x1080", "menu_resolution_set_custom 1920 1080" + Command "(1440p HD) 2560x1440", "menu_resolution_set_custom 2560 1440" + Command "(4K UHD) 3840x2160", "menu_resolution_set_custom 3840 2160" + StaticText "" + StaticText "$VIDMNU_ASPECT1610" + Command "960x600", "menu_resolution_set_custom 960 600" + Command "1280x800", "menu_resolution_set_custom 1280 800" + Command "1440x900", "menu_resolution_set_custom 1440 900" + Command "1680x1050", "menu_resolution_set_custom 1680 1050" + Command "1920x1200", "menu_resolution_set_custom 1920 1200" +} + + +//------------------------------------------------------------------------------------------- +// +// Misc menu +// +//------------------------------------------------------------------------------------------- + +OptionValue Autosave +{ + 0, "$OPTVAL_ALWAYS" + 1, "$OPTVAL_SCRIPTSONLY" + 2, "$OPTVAL_NEVER" +} + +OptionMenu "MiscOptions" //protected +{ + Title "$MISCMNU_TITLE" + //Indent 220 + IfOption(Windows) + { + Option "$MISCMNU_WINFULLSCREENTOGGLE", "k_allowfullscreentoggle", "OnOff" + } + IfOption(Mac) + { + Option "$MISCMNU_MACFULLSCREENTOGGLE", "k_allowfullscreentoggle", "OnOff" + } + Option "$MISCMNU_QUERYIWAD", "queryiwad", "OnOff" + StaticText " " + //Option "$MISCMNU_ALLCHEATS", "allcheats", "OnOff" + Option "$MISCMNU_ENABLEAUTOSAVES", "disableautosave", "Autosave" + //Option "$MISCMNU_SAVELOADCONFIRMATION", "saveloadconfirmation", "OnOff" + Slider "$MISCMNU_AUTOSAVECOUNT", "autosavecount", 1, 20, 1, 0 + //Option "$MISCMNU_QUICKSAVEROTATION", "quicksaverotation", "OnOff" + Slider "$MISCMNU_QUICKSAVECOUNT", "quicksaverotationcount", 1, 20, 1, 0 + Option "$MISCMNU_INTERSCROLL", "nointerscrollabort", "OffOn" + ifgame(shadowwarrior) + { + Option "$MISCMNU_DARTS", "sw_darts", "OnOff" + Option "$MISCMNU_NINJA", "sw_ninjahack", "OnOff" + } + //StaticText " " + //Option "$OPTMNU_LANGUAGE", "language", "LanguageOptions" - not ready yet + +} + + +//------------------------------------------------------------------------------------------- +// +// No multiplayer support for now, but kept for documentation. +// +//------------------------------------------------------------------------------------------- + +LISTMENU "MultiMenu" +{ + ifgame(Duke, Nam, WW2GI, Fury) + { + position 160, 55, 135 + centermenu + fixedspacing 5 + ifgame(Duke, Nam, WW2GI, Fury) + { + class "Duke.ListMenu" + } + else + { + class "Redneck.ListMenu" + } + animatedtransition + NativeTextItem "$MNU_PLAYERSETUP", "p", "PlayerSetupMenu" + } + ifgame(blood) + { + position 160, 80, 150 + class "Blood.ListMenu" + centermenu + Linespacing 20 + } + ifgame(shadowwarrior) + { + position 160, 80, 150 + class "ShadowWarrior.ListMenu" + centermenu + Linespacing 20 + } + + Caption "$MNU_NETWORKGAME" + NativeTextItem "$MNU_JOINGAME", "j", "JoinGameMenu" + NativeTextItem "$MNU_HOSTGAME", "h", "HostGameMenu" +} + +OptionMenu "HostGameMenu" +{ + title "$MNU_HOSTGAME" + Submenu "$NETMNU_OPTIONS", "MultiOptionsMenu" + Command "$NETMNU_LAUNCH", "Launch_MP" // currently a no-op +} + +OptionMenu "JoinGameMenu" +{ + TextField "$NETMNU_SERVER", "m_server" + TextField "$NETMNU_PORT", "m_netport" + SafeCommand "$NETMNU_CONNECT", "MultiConnect" +} + +OptionValue "MultiGameType" +{ + 0, "$NETMNU_GAMETYPE1" + 1, "$NETMNU_GAMETYPE2" + 2, "$NETMNU_GAMETYPE3" + 3, "$NETMNU_GAMETYPE4" + 4, "$NETMNU_GAMETYPE5" +} + +OptionValue "MultiEpisode" +{ + 0, "1" + 0, "2" + 0, "3" + 0, "4" + 0, "5" + 0, "6" + 0, "7" +} + +OptionMenu "MultiOptionsMenu" +{ + title "$NETMNU_OPTIONS" + Option "$NETMNU_GAMETYPE", "m_coop", "MultiGameType" + Option "$NETMNU_EPISODE", "m_episode_number", "MultiEpisode" + Option "$NETMNU_LEVEL", "m_level_number", "MultiEpisode" + Submenu "$MNU_USERMAP", "MultiUserMap" // todo: fileselect item + Option "$NETMNU_MONSTERS", "m_monsters", "OnOff" + Option "$NETMNU_MARKERS", "m_marker", "OnOff" + Option "$NETMNU_MAPEXITS", "m_noexit", "OnOff" + Option "$NETMNU_FFIRE", "m_ffire", "OnOff" + SafeCommand "$NETMNU_ACCEPT", "MultiAccept" +} diff --git a/wadsrc/static/demolition/origbinds.txt b/wadsrc/static/demolition/origbinds.txt new file mode 100644 index 000000000..723b9b43c --- /dev/null +++ b/wadsrc/static/demolition/origbinds.txt @@ -0,0 +1,19 @@ +uparrow "+Move_Forward" +downarrow "+Move_Backward" +LCtrl "+Fire" +Space "+Open" +A "+Jump" +/ "+Jump" +Z "+Crouch" +KP9 "+Look_Up" +KP3 "+Look_Down" +KP. "+Look_Right" +, "+Strafe_Left" +. "+Strafe_Right" +KP7 "+Aim_Up" +KP1 "+Aim_Down" +KP5 "+Center_View" +KP- "+Shrink_Screen" +KP+ "+Enlarge_Screen" +U "+Mouse_Aiming" +I "+Toggle_Crosshair" diff --git a/wadsrc/static/textcolors.txt b/wadsrc/static/demolition/textcolors.txt similarity index 100% rename from wadsrc/static/textcolors.txt rename to wadsrc/static/demolition/textcolors.txt diff --git a/wadsrc/static/filter/blood/demolition/defbinds.txt b/wadsrc/static/filter/blood/demolition/defbinds.txt index 1f10c0029..0713276f9 100644 --- a/wadsrc/static/filter/blood/demolition/defbinds.txt +++ b/wadsrc/static/filter/blood/demolition/defbinds.txt @@ -1,75 +1,11 @@ -W "+Move_Forward" -KP8 "+Move_Forward" -S "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -Backspace "+Turn_Around" -LAlt "+Strafe" -RAlt "+Strafe" -A "+Strafe_Left" -D "+Strafe_Right" -Space "+Jump" -/ "+Jump" -LCtrl "+Crouch" -LShift "+Run" -RShift "+Run" -Capslock "+AutoRun" -E "+Open" -RCtrl "+Fire" -X "+Alt_Fire" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -KP5 "+Center_View" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" -Tab "+Map" -F "+Map_Follow_Mode" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -T "+Send_Message" -K "+See_Coop_View" -F7 "+See_Chase_View" U "+Mouse_Aiming" I "+Toggle_Crosshair" -' "+Next_Weapon" -; "+Previous_Weapon" Scroll "+Holster_Weapon" -Y "+Show_Opponents_Weapon" B "+BeastVision" C "+CrystalBall" -J "+JetPack" -M "+MedKit" P "+ProximityBombs" R "+RemoteBombs" -` "toggleconsole" -Mouse1 "+Fire" +X "+Alt_Fire" +J "+Jetpack" +M "+MedKit" Mouse2 "+Alt_Fire" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/blood/demolition/leftbinds.txt b/wadsrc/static/filter/blood/demolition/leftbinds.txt index 17101dbe1..6bd24ae48 100644 --- a/wadsrc/static/filter/blood/demolition/leftbinds.txt +++ b/wadsrc/static/filter/blood/demolition/leftbinds.txt @@ -1,72 +1,9 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -Backspace "+Turn_Around" -LAlt "+Strafe" -RAlt "+Strafe" -, "+Strafe_Left" -KP7 "+Strafe_Left" -. "+Strafe_Right" -KP9 "+Strafe_Right" -A "+Jump" -KP- "+Jump" -Z "+Crouch" -LShift "+Run" -RShift "+Run" -Capslock "+AutoRun" -Space "+Open" -LCtrl "+Fire" -RCtrl "+Fire" -X "+Alt_Fire" -Home "+Aim_Up" -End "+Aim_Down" -PgUp "+Look_Up" -PgDn "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" -Tab "+Map" -F "+Map_Follow_Mode" -- "+Shrink_Screen" -= "+Enlarge_Screen" -T "+Send_Message" -K "+See_Coop_View" -F7 "+Third_Person_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -' "+Next_Weapon" -; "+Previous_Weapon" -Scroll "+Holster_Weapon" +// W "+Show_Opponents_Weapon" B "+BeastVision" C "+CrystalBall" -J "+JetPack" -M "+MedKit" P "+ProximityBombs" R "+RemoteBombs" -` "toggleconsole" -Mouse1 "+Fire" -Mouse2 "+Open" -Mouse3 "+Run" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" +X "+Alt_Fire" +J "+Jetpack" +M "+MedKit" diff --git a/wadsrc/static/filter/blood/demolition/origbinds.txt b/wadsrc/static/filter/blood/demolition/origbinds.txt index 192221292..29c8ef5d5 100644 --- a/wadsrc/static/filter/blood/demolition/origbinds.txt +++ b/wadsrc/static/filter/blood/demolition/origbinds.txt @@ -1,67 +1,5 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -Backspace "+Turn_Around" -LAlt "+Strafe" -RAlt "+Strafe" -, "+Strafe_Left" -. "+Strafe_Right" -A "+Jump" -/ "+Jump" -Z "+Crouch" -LShift "+Run" -RShift "+Run" -Capslock "+AutoRun" -Space "+Open" -LCtrl "+Fire" -RCtrl "+Fire" +// X "+Alt_Fire" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -KP5 "+Center_View" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" -Tab "+Map" -F "+Map_Follow_Mode" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -T "+Send_Message" -K "+See_Coop_View" -F7 "+Third_Person_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -' "+Next_Weapon" -; "+Previous_Weapon" -Scroll "+Holster_Weapon" W "+Show_Opponents_Weapon" B "+BeastVision" C "+CrystalBall" @@ -69,8 +7,4 @@ J "+JetPack" M "+MedKit" P "+ProximityBombs" R "+RemoteBombs" -` "toggleconsole" -Mouse1 "+Fire" Mouse2 "+Alt_Fire" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/blood/tiles/2574.png b/wadsrc/static/filter/blood/tiles/2574.png index a3a76ec3b..cb5d3aa41 100644 Binary files a/wadsrc/static/filter/blood/tiles/2574.png and b/wadsrc/static/filter/blood/tiles/2574.png differ diff --git a/wadsrc/static/filter/duke/demolition/defbinds.txt b/wadsrc/static/filter/duke/demolition/defbinds.txt index c42bb1742..04f510ffb 100644 --- a/wadsrc/static/filter/duke/demolition/defbinds.txt +++ b/wadsrc/static/filter/duke/demolition/defbinds.txt @@ -1,77 +1,11 @@ -W "+Move_Forward" -KP8 "+Move_Forward" -S "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -RCtrl "+Fire" -E "+Open" -LShift "+Run" -RShift "+Run" -Space "+Jump" -/ "+Jump" -LCtrl "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -A "+Strafe_Left" -D "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +// +R "+Steroids" +Q "+Quick_Kick" H "+Holo_Duke" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -Y "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -R "+Steroids" -Q "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Capslock "+AutoRun" X "+Last_Used_Weapon" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" C "+Toggle_Crouch" -Mouse1 "+Fire" Mouse2 "+Jetpack" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/duke/demolition/leftbinds.txt b/wadsrc/static/filter/duke/demolition/leftbinds.txt index cd2f8dbfe..953ecd791 100644 --- a/wadsrc/static/filter/duke/demolition/leftbinds.txt +++ b/wadsrc/static/filter/duke/demolition/leftbinds.txt @@ -1,71 +1,7 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -Space "+Open" -LShift "+Run" -RShift "+Run" -A "+Jump" -KP- "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -PgDn "+Look_Down" -Ins "+Look_Left" -Del "+Look_Right" -, "+Strafe_Left" -KP7 "+Strafe_Left" -. "+Strafe_Right" -KP9 "+Strafe_Right" -Home "+Aim_Up" -End "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" H "+Holo_Duke" +R "+Steroids" +Q "+Quick_Kick" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -= "+Enlarge_Screen" -Scroll "+Holster_Weapon" W "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -R "+Steroids" -Q "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Capslock "+AutoRun" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" -Mouse2 "+Open" -Mouse3 "+Run" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/duke/demolition/origbinds.txt b/wadsrc/static/filter/duke/demolition/origbinds.txt index 8f0bf2ccc..62770c115 100644 --- a/wadsrc/static/filter/duke/demolition/origbinds.txt +++ b/wadsrc/static/filter/duke/demolition/origbinds.txt @@ -1,78 +1,13 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -Space "+Open" -LShift "+Run" -RShift "+Run" -A "+Jump" -/ "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -. "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +// +R "+Steroids" +` "+Quick_Kick" +W "+Show_Opponents_Weapon" H "+Holo_Duke" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -W "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -R "+Steroids" -` "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" C "toggleconsole" -Capslock "+AutoRun" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" Mouse2 "+Jetpack" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" + + \ No newline at end of file diff --git a/wadsrc/static/filter/ionfury/demolition/defbinds.txt b/wadsrc/static/filter/ionfury/demolition/defbinds.txt index 0d6cfee6a..f0e5627be 100644 --- a/wadsrc/static/filter/ionfury/demolition/defbinds.txt +++ b/wadsrc/static/filter/ionfury/demolition/defbinds.txt @@ -1,71 +1,8 @@ -W "+Move_Forward" -KP8 "+Move_Forward" -S "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -RCtrl "+Fire" -E "+Open" -LShift "+Run" -RShift "+Run" -Space "+Jump" -/ "+Jump" -LCtrl "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -A "+Strafe_Left" -D "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -Y "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Capslock "+AutoRun" +// X "+Last_Used_Weapon" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" C "+Toggle_Crouch" -Mouse1 "+Fire" -Mouse2 "+Jetpack" +Mouse2 "+Steroids" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" +Pad_Y "+Steroids" +DPadLeft "+MedKit" +DPadRight "+Nightvision" diff --git a/wadsrc/static/filter/ionfury/demolition/graphics/M_BACK.png b/wadsrc/static/filter/ionfury/demolition/graphics/M_BACK.png new file mode 100644 index 000000000..84a57c49c Binary files /dev/null and b/wadsrc/static/filter/ionfury/demolition/graphics/M_BACK.png differ diff --git a/wadsrc/static/filter/ionfury/demolition/leftbinds.txt b/wadsrc/static/filter/ionfury/demolition/leftbinds.txt index 30a7a866c..8b448ee89 100644 --- a/wadsrc/static/filter/ionfury/demolition/leftbinds.txt +++ b/wadsrc/static/filter/ionfury/demolition/leftbinds.txt @@ -1,69 +1 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -Space "+Open" -LShift "+Run" -RShift "+Run" -A "+Jump" -KP- "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -KP7 "+Strafe_Left" -. "+Strafe_Right" -KP9 "+Strafe_Right" -Home "+Aim_Up" -End "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -= "+Enlarge_Screen" -Scroll "+Holster_Weapon" W "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Capslock "+AutoRun" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" -Mouse2 "+Open" -Mouse3 "+Run" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/ionfury/demolition/origbinds.txt b/wadsrc/static/filter/ionfury/demolition/origbinds.txt index b3c3a0a63..dcd40b932 100644 --- a/wadsrc/static/filter/ionfury/demolition/origbinds.txt +++ b/wadsrc/static/filter/ionfury/demolition/origbinds.txt @@ -1,72 +1,6 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -Space "+Open" -LShift "+Run" -RShift "+Run" -A "+Jump" -/ "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -. "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" W "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -' "+Next_Weapon" -; "+Previous_Weapon" -C "toggleconsole" -Capslock "+AutoRun" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" -Mouse2 "+Jetpack" +Mouse2 "+Steroids" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" +Pad_Y "+Steroids" +DPadLeft "+MedKit" +DPadRight "+Nightvision" diff --git a/wadsrc/static/filter/nam/demolition/defbinds.txt b/wadsrc/static/filter/nam/demolition/defbinds.txt index c42bb1742..04f510ffb 100644 --- a/wadsrc/static/filter/nam/demolition/defbinds.txt +++ b/wadsrc/static/filter/nam/demolition/defbinds.txt @@ -1,77 +1,11 @@ -W "+Move_Forward" -KP8 "+Move_Forward" -S "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -RCtrl "+Fire" -E "+Open" -LShift "+Run" -RShift "+Run" -Space "+Jump" -/ "+Jump" -LCtrl "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -A "+Strafe_Left" -D "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +// +R "+Steroids" +Q "+Quick_Kick" H "+Holo_Duke" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -Y "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -R "+Steroids" -Q "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Capslock "+AutoRun" X "+Last_Used_Weapon" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" C "+Toggle_Crouch" -Mouse1 "+Fire" Mouse2 "+Jetpack" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/nam/demolition/graphics/M_BACK.png b/wadsrc/static/filter/nam/demolition/graphics/M_BACK.png new file mode 100644 index 000000000..32e49b863 Binary files /dev/null and b/wadsrc/static/filter/nam/demolition/graphics/M_BACK.png differ diff --git a/wadsrc/static/filter/nam/demolition/leftbinds.txt b/wadsrc/static/filter/nam/demolition/leftbinds.txt index 7006cc1eb..953ecd791 100644 --- a/wadsrc/static/filter/nam/demolition/leftbinds.txt +++ b/wadsrc/static/filter/nam/demolition/leftbinds.txt @@ -1,75 +1,7 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -Space "+Open" -LShift "+Run" -RShift "+Run" -A "+Jump" -KP- "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -KP7 "+Strafe_Left" -. "+Strafe_Right" -KP9 "+Strafe_Right" -Home "+Aim_Up" -End "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" H "+Holo_Duke" +R "+Steroids" +Q "+Quick_Kick" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -= "+Enlarge_Screen" -Scroll "+Holster_Weapon" W "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -R "+Steroids" -Q "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Capslock "+AutoRun" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" -Mouse2 "+Open" -Mouse3 "+Run" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/nam/demolition/origbinds.txt b/wadsrc/static/filter/nam/demolition/origbinds.txt index 8f0bf2ccc..62770c115 100644 --- a/wadsrc/static/filter/nam/demolition/origbinds.txt +++ b/wadsrc/static/filter/nam/demolition/origbinds.txt @@ -1,78 +1,13 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -Space "+Open" -LShift "+Run" -RShift "+Run" -A "+Jump" -/ "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -. "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +// +R "+Steroids" +` "+Quick_Kick" +W "+Show_Opponents_Weapon" H "+Holo_Duke" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -W "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -R "+Steroids" -` "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" C "toggleconsole" -Capslock "+AutoRun" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" Mouse2 "+Jetpack" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" + + \ No newline at end of file diff --git a/wadsrc/static/filter/redneck/demolition/defbinds.txt b/wadsrc/static/filter/redneck/demolition/defbinds.txt index 41aaede53..1abda301e 100644 --- a/wadsrc/static/filter/redneck/demolition/defbinds.txt +++ b/wadsrc/static/filter/redneck/demolition/defbinds.txt @@ -1,77 +1,11 @@ -W "+Move_Forward" -KP8 "+Move_Forward" -S "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -RCtrl "+Fire" -E "+Open" -LShift "+Run" -RShift "+Run" -Capslock "+AutoRun" -Space "+Jump" -/ "+Jump" -LCtrl "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -A "+Strafe_Left" -D "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +// +V "+Show_Opponents_Weapon" B "+Holo_Duke" C "+Jetpack" Y "+NightVision" R "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -E "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" M "+Steroids" Q "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -+ "+Dpad_Select" X "+Last_Used_Weapon" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" Mouse2 "+Jetpack" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/redneck/demolition/graphics/M_BACK.png b/wadsrc/static/filter/redneck/demolition/graphics/M_BACK.png new file mode 100644 index 000000000..32e49b863 Binary files /dev/null and b/wadsrc/static/filter/redneck/demolition/graphics/M_BACK.png differ diff --git a/wadsrc/static/filter/redneck/demolition/leftbinds.txt b/wadsrc/static/filter/redneck/demolition/leftbinds.txt index abe5376c6..519dd5c20 100644 --- a/wadsrc/static/filter/redneck/demolition/leftbinds.txt +++ b/wadsrc/static/filter/redneck/demolition/leftbinds.txt @@ -1,74 +1,7 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -LCtrl "+Fire" -RCtrl "+Fire" -LShift "+Run" -RShift "+Run" -Capslock "+AutoRun" -A "+Jump" -KP- "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -PgDn "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -KP7 "+Strafe_Left" -. "+Strafe_Right" -KP9 "+Strafe_Right" -Home "+Aim_Up" -End "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +E "+Show_Opponents_Weapon" +M "+Steroids" +Q "+Quick_Kick" B "+Holo_Duke" C "+Jetpack" Y "+NightVision" W "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -= "+Enlarge_Screen" -Scroll "+Holster_Weapon" -E "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -M "+Steroids" -Q "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" -Mouse2 "+Open" -Mouse3 "+Run" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/redneck/demolition/origbinds.txt b/wadsrc/static/filter/redneck/demolition/origbinds.txt index 978b05640..0fc752ee2 100644 --- a/wadsrc/static/filter/redneck/demolition/origbinds.txt +++ b/wadsrc/static/filter/redneck/demolition/origbinds.txt @@ -1,74 +1,8 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -LCtrl "+Fire" -RCtrl "+Fire" -LShift "+Run" -RShift "+Run" -Capslock "+AutoRun" -A "+Jump" -/ "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -. "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +V "toggleconsole" +E "+Show_Opponents_Weapon" +M "+Steroids" +` "+Quick_Kick" B "+Holo_Duke" C "+Jetpack" Y "+NightVision" W "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -E "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -M "+Steroids" -` "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -V "toggleconsole" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" diff --git a/wadsrc/static/filter/shadowwarrior.wanton/SWCustom.txt b/wadsrc/static/filter/shadowwarrior.wanton/SWCustom.txt new file mode 100644 index 000000000..de7cf7ea0 --- /dev/null +++ b/wadsrc/static/filter/shadowwarrior.wanton/SWCustom.txt @@ -0,0 +1,154 @@ + +level 5 +{ + title "$TXTS_W_MAP01" + filename "$whirl.map" + song "yokoha03.mid" + cdatrack 5 + besttime 330 + partime 600 +} +level 6 +{ + title "$TXTS_W_MAP02" + filename "$tank.map" + song "nippon34.mid" + cdatrack 6 + besttime 120 + partime 240 +} +level 7 +{ + title "$TXTS_W_MAP03" + filename "$boat.map" + song "execut11.mid" + cdatrack 8 + besttime 120 + partime 240 +} +level 8 +{ + title "$TXTS_W_MAP04" + filename "$garden.map" + song "execut11.mid" + cdatrack 11 + besttime 66 + partime 120 +} +level 9 +{ + title "$TXTS_W_MAP05" + filename "$outpost.map" + song "sanai.mid" + cdatrack 12 + besttime 90 + partime 180 +} +level 10 +{ + title "$TXTS_W_MAP06" + filename "$hidtemp.map" + song "kotec2.mid" + cdatrack 5 + besttime 125 + partime 250 +} +level 11 +{ + title "$TXTS_W_MAP07" + filename "$plax1.map" + song "kotec2.mid" + cdatrack 10 + besttime 392 + partime 720 +} +level 12 +{ + title "$TXTS_W_MAP08" + filename "$bath.map" + song "yokoha03" + cdatrack 4 + besttime 600 + partime 600 +} +level 13 +{ + title "$TXTS_W_MAP09" + filename "$airport.map" + song "nippon34" + cdatrack 6 + besttime 180 + partime 300 +} +level 20 +{ + title "$TXTS_W_MAP10" + filename "$volcano.map" + song "" + cdatrack 10 + besttime 554 + partime 660 +} +level 21 +{ + title "$TXTS_W_MAP11" + filename "$shore.map" + song "" + cdatrack 11 + besttime 240 + partime 480 +} +level 22 +{ + title "$TXTS_W_MAP12" + filename "$auto.map" + song "" + cdatrack 5 + besttime 247 + partime 480 +} +level 23 +{ + title "$TXTS_W_MAP13" + filename "tank.map" + song "" + cdatrack 11 + besttime 600 + partime 600 +} +level 24 +{ + title "$TXTS_W_MAP14" + filename "$dmwoods.map" + song "" + cdatrack 8 + besttime 600 + partime 600 +} +level 25 +{ + title "$TXTS_W_MAP15" + filename "$dmshrin.map" + song "" + cdatrack 7 + besttime 600 + partime 600 +} +level 27 +{ + title "$TXTS_W_MAP16" + filename "shotgun.map" + song "" + cdatrack 5 + besttime 600 + partime 600 +} +episode 1 +{ + title "" +} +episode 2 +{ + title "$TXTS_W_EP" + subtitle "" +} diff --git a/wadsrc/static/filter/shadowwarrior.shadowwarrior/SWCustom.txt b/wadsrc/static/filter/shadowwarrior/demolition/SWCustom.txt similarity index 60% rename from wadsrc/static/filter/shadowwarrior.shadowwarrior/SWCustom.txt rename to wadsrc/static/filter/shadowwarrior/demolition/SWCustom.txt index 4372f00cc..bf0703a04 100644 --- a/wadsrc/static/filter/shadowwarrior.shadowwarrior/SWCustom.txt +++ b/wadsrc/static/filter/shadowwarrior/demolition/SWCustom.txt @@ -1,6 +1,6 @@ level 1 { - title "Seppuku Station" + title "$TXTS_MAP01" filename "$bullet.map" song "e1l01.mid" cdatrack 4 @@ -9,7 +9,7 @@ level 1 } level 2 { - title "Zilla Construction" + title "$TXTS_MAP02" filename "$dozer.map" song "e1l03.mid" cdatrack 9 @@ -18,7 +18,7 @@ level 2 } level 3 { - title "Master Leep's Temple" + title "$TXTS_MAP03" filename "$shrine.map" song "e1l02.mid" cdatrack 12 @@ -27,7 +27,7 @@ level 3 } level 4 { - title "Dark Woods of the Serpent" + title "$TXTS_MAP04" filename "$woods.map" song "e1l04.mid" cdatrack 10 @@ -36,7 +36,7 @@ level 4 } level 5 { - title "Rising Son" + title "$TXTS_MAP05" filename "$whirl.map" song "yokoha03.mid" cdatrack 5 @@ -45,7 +45,7 @@ level 5 } level 6 { - title "Killing Fields" + title "$TXTS_MAP06" filename "$tank.map" song "nippon34.mid" cdatrack 6 @@ -54,7 +54,7 @@ level 6 } level 7 { - title "Hara-Kiri Harbor" + title "$TXTS_MAP07" filename "$boat.map" song "execut11.mid" cdatrack 8 @@ -63,7 +63,7 @@ level 7 } level 8 { - title "Zilla's Villa" + title "$TXTS_MAP08" filename "$garden.map" song "execut11.mid" cdatrack 11 @@ -72,7 +72,7 @@ level 8 } level 9 { - title "Monastery" + title "$TXTS_MAP09" filename "$outpost.map" song "sanai.mid" cdatrack 12 @@ -81,7 +81,7 @@ level 9 } level 10 { - title "Raider of the Lost Wang" + title "$TXTS_MAP10" filename "$hidtemp.map" song "kotec2.mid" cdatrack 5 @@ -90,7 +90,7 @@ level 10 } level 11 { - title "Sumo Sky Palace" + title "$TXTS_MAP11" filename "$plax1.map" song "kotec2.mid" cdatrack 10 @@ -99,7 +99,7 @@ level 11 } level 12 { - title "Bath House" + title "$TXTS_MAP12" filename "$bath.map" song "yokoha03" cdatrack 4 @@ -108,7 +108,7 @@ level 12 } level 13 { - title "Unfriendly Skies" + title "$TXTS_MAP13" filename "$airport.map" song "nippon34" cdatrack 6 @@ -117,7 +117,7 @@ level 13 } level 14 { - title "Crude Oil" + title "$TXTS_MAP14" filename "$refiner.map" song "kotoki12.mid" cdatrack 9 @@ -126,7 +126,7 @@ level 14 } level 15 { - title "Coolie Mines" + title "$TXTS_MAP15" filename "$newmine.map" song "hoshia02.mid" cdatrack 7 @@ -135,7 +135,7 @@ level 15 } level 16 { - title "Subpen 7" + title "$TXTS_MAP16" filename "$subbase.map" song "hoshia02.mid" cdatrack 10 @@ -144,7 +144,7 @@ level 16 } level 17 { - title "The Great Escape" + title "$TXTS_MAP17" filename "$rock.map" song "" cdatrack 8 @@ -153,7 +153,7 @@ level 17 } level 18 { - title "Floating Fortress" + title "$TXTS_MAP18" filename "$yamato.map" song "sanai.mid" cdatrack 7 @@ -162,7 +162,7 @@ level 18 } level 19 { - title "Water Torture" + title "$TXTS_MAP19" filename "$seabase.map" song "kotec2.mid" cdatrack 9 @@ -171,7 +171,7 @@ level 19 } level 20 { - title "Stone Rain" + title "$TXTS_MAP20" filename "$volcano.map" song "" cdatrack 10 @@ -180,7 +180,7 @@ level 20 } level 21 { - title "Shanghai Shipwreck" + title "$TXTS_MAP21" filename "$shore.map" song "" cdatrack 11 @@ -189,7 +189,7 @@ level 21 } level 22 { - title "Auto Maul" + title "$TXTS_MAP22" filename "$auto.map" song "" cdatrack 5 @@ -198,7 +198,7 @@ level 22 } level 23 { - title "Heavy Metal (DM only)" + title "$TXTS_MAP23" filename "tank.map" song "" cdatrack 11 @@ -207,7 +207,7 @@ level 23 } level 24 { - title "Ripper Valley (DM only)" + title "$TXTS_MAP24" filename "$dmwoods.map" song "" cdatrack 8 @@ -216,7 +216,7 @@ level 24 } level 25 { - title "House of Wang (DM only)" + title "$TXTS_MAP25" filename "$dmshrin.map" song "" cdatrack 7 @@ -225,7 +225,7 @@ level 25 } level 26 { - title "Lo Wang Rally (DM only" + title "$TXTS_MAP26" filename "$rush.map" song "" cdatrack 13 @@ -234,7 +234,7 @@ level 26 } level 27 { - title "Ruins of the Ronin (CTF)" + title "$TXTS_MAP27" filename "shotgun.map" song "" cdatrack 5 @@ -243,7 +243,7 @@ level 27 } level 28 { - title "Killing Fields (CTF)" + title "$TXTS_MAP28" filename "$dmdrop.map" song "" cdatrack 6 @@ -252,101 +252,101 @@ level 28 } episode 1 { - title "Enter the Wang" - subtitle "Four levels (Shareware Version)" + title "$TXTS_EP1" + subtitle "$TXTS_EPD1" } episode 2 { - title "Code of Honor" - subtitle "Eighteen levels (Full Version Only)" + title "$TXTS_EP2" + subtitle "$TXTS_EPD2" } skill 1 { - name "Tiny Grasshopper" + name "$TXTS_SK1" } skill 2 { - name "I Have No Fear" + name "$TXTS_SK2" } skill 3 { - name "Who Wants Wang" + name "$TXTS_SK3" } skill 4 { - name "No Pain, No Gain" + name "$TXTS_SK4" } -/* + inventory 1 { - name "Armor Vest +50" + name "$TXTS_INV1" amount 50 } inventory 2 { - name "Kevlar Armor Vest +100" + name "$TXTS_INV2" amount 100 } inventory 3 { - name "MedKit +20" + name "$TXTS_INV3" amount 20 } inventory 4 { - name "Fortune Cookie +50 BOOST" + name "$TXTS_INV4" amount 50 } inventory 5 { - name "Portable MedKit" + name "$TXTS_INV5" amount 100 } inventory 6 { - name "Gas Bomb" + name "$TXTS_INV6" amount 1 } inventory 7 { - name "Flash Bomb" + name "$TXTS_INV7" amount 2 } inventory 8 { - name "Caltrops" + name "$TXTS_INV8" amount 3 } inventory 9 { - name "Night Vision Goggles" + name "$TXTS_INV9" amount 100 } inventory 10 { - name "Repair Kit" + name "$TXTS_INV10" amount 100 } inventory 11 { - name "Smoke Bomb" + name "$TXTS_INV11" amount 100 } weapon 1 { - name "Fists" + name "$TXTS_WEAP1" mindamage 10 maxdamage 40 } weapon 2 { - name "Sword" + name "$TXTS_WEAP2" mindamage 50 maxdamage 80 } weapon 3 { - name "Shurikens" + name "$TXTS_WEAP3" ammoname "" maxammo 99 mindamage 5 @@ -356,7 +356,7 @@ weapon 3 } weapon 4 { - name "Sticky Bombs" + name "$TXTS_WEAP4" ammoname "" maxammo 20 mindamage 5 @@ -366,8 +366,8 @@ weapon 4 } weapon 5 { - name "UZI Submachine Gun" - ammoname "UZI Clip" + name "$TXTS_WEAP5" + ammoname "$TXTS_AMMO5" maxammo 200 mindamage 5 maxdamage 7 @@ -376,8 +376,8 @@ weapon 5 } weapon 6 { - name "Missile Launcher" - ammoname "Missiles" + name "$TXTS_WEAP6" + ammoname "$TXTS_AMMO6" maxammo 50 mindamage 15 maxdamage 30 @@ -386,8 +386,8 @@ weapon 6 } weapon 7 { - name "Nuclear Warhead" - ammoname "" + name "$TXTS_WEAP7" + ammoname "$TXTS_AMMO7" maxammo 0 mindamage 0 maxdamage 800 @@ -396,8 +396,8 @@ weapon 7 } weapon 8 { - name "Grenade Launcher" - ammoname "Grenade Shells" + name "$TXTS_WEAP8" + ammoname "$TXTS_AMMO8" maxammo 50 mindamage 15 maxdamage 30 @@ -406,8 +406,8 @@ weapon 8 } weapon 9 { - name "Rail Gun" - ammoname "Rail Gun Rods" + name "$TXTS_WEAP9" + ammoname "$TXTS_AMMO9" maxammo 20 mindamage 40 maxdamage 60 @@ -416,8 +416,8 @@ weapon 9 } weapon 10 { - name "Riot Gun" - ammoname "Shotshells" + name "$TXTS_WEAP10" + ammoname "$TXTS_AMMO10" maxammo 52 mindamage 4 maxdamage 4 @@ -426,8 +426,8 @@ weapon 10 } weapon 11 { - name "Guardian Head" - ammoname "Firebursts" + name "$TXTS_WEAP11" + ammoname "$TXTS_AMMO11" maxammo 80 mindamage 10 maxdamage 25 @@ -436,8 +436,8 @@ weapon 11 } weapon 12 { - name "Ripper Heart" - ammoname "Deathcoils" + name "$TXTS_WEAP12" + ammoname "$TXTS_AMMO12" maxammo 5 mindamage 75 maxdamage 100 @@ -446,51 +446,44 @@ weapon 12 } fortune { - "You never going to score." - "26-31-43-82-16-29" - "Sorry, you no win this time, try again." - "You try harder get along. Be a nice man." - "No man is island, except Lo Wang." - "There is much death in future." - "You should kill all business associates." - "(c)1997,3DRealms fortune cookie company." - "Your chi attracts many chicks." - "Don't you know you the scum of society!?" - "You should not scratch yourself there." - "Man who stand on toilet, high on pot." - "Man who fart in church sit in own pew." - "Man trapped in pantry has ass in jam." - "Baseball wrong. Man with 4 balls cannot walk." - "Man who buy drowned cat pay for wet pussy." + "$TXTS_COOKIE1" + "$TXTS_COOKIE2" + "$TXTS_COOKIE3" + "$TXTS_COOKIE4" + "$TXTS_COOKIE5" + "$TXTS_COOKIE6" + "$TXTS_COOKIE7" + "$TXTS_COOKIE8" + "$TXTS_COOKIE9" + "$TXTS_COOKIE10" + "$TXTS_COOKIE11" + "$TXTS_COOKIE12" + "$TXTS_COOKIE13" + "$TXTS_COOKIE14" + "$TXTS_COOKIE15" + "$TXTS_COOKIE16" } gotkey { - "Got the RED key!" - "Got the BLUE key!" - "Got the GREEN key!" - "Got the YELLOW key!" - "Got the GOLD master key!" - "Got the SILVER master key!" - "Got the BRONZE master key!" - "Got the RED master key!" + "$TXTS_KEY1" + "$TXTS_KEY2" + "$TXTS_KEY3" + "$TXTS_KEY4" + "$TXTS_KEY5" + "$TXTS_KEY6" + "$TXTS_KEY7" + "$TXTS_KEY8" } needkey { - "You need a RED key for this door." - "You need a BLUE key for this door." - "You need a GREEN key for this door." - "You need a YELLOW key for this door." - "You need a GOLD key for this door." - "You need a SILVER key for this door." - "You need a BRONZE key for this door." - "You need a RED key for this door." -} -animation -{ - "SwpAnim.zip" // Swp1001.. 43 frames org = sw.anm - "swend.anm" // Swp2001.. 70 - "sumocinm.anm" // Swp3001.. 84 - "zfcin.anm" // Swp4001.. 142 + "$TXTS_DOOR1" + "$TXTS_DOOR2" + "$TXTS_DOOR3" + "$TXTS_DOOR4" + "$TXTS_DOOR5" + "$TXTS_DOOR6" + "$TXTS_DOOR7" + "$TXTS_DOOR8" } theme 1 // game startup menu { @@ -522,4 +515,3 @@ theme 6 // game end sequence song "ending.mid" cdatrack 14 } -*/ \ No newline at end of file diff --git a/wadsrc/static/filter/shadowwarrior/demolition/defbinds.txt b/wadsrc/static/filter/shadowwarrior/demolition/defbinds.txt index e3d8597b0..43932258a 100644 --- a/wadsrc/static/filter/shadowwarrior/demolition/defbinds.txt +++ b/wadsrc/static/filter/shadowwarrior/demolition/defbinds.txt @@ -1,43 +1,9 @@ -W "+Move_Forward" -S "+Move_Backward" -E "+Open" -LShift "+Run" -Capslock "+AutoRun" -Space "+Jump" -LAlt "+Crouch" -A "+Strafe_Left" -D "+Strafe_Right" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +// +I "+Toggle_Crosshair" +Mouse2 "+MediKit" M "+MedKit" B "+Smoke_Bomb" N "+Nightvision" G "+Gas_Bomb" F "+Flash_Bomb" C "+Caltrops" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -= "+Enlarge_Screen" -H "+Holster_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -` "toggleconsole" -Mouse1 "+Fire" -Mouse2 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/shadowwarrior/demolition/leftbinds.txt b/wadsrc/static/filter/shadowwarrior/demolition/leftbinds.txt index 9395911f3..39c294001 100644 --- a/wadsrc/static/filter/shadowwarrior/demolition/leftbinds.txt +++ b/wadsrc/static/filter/shadowwarrior/demolition/leftbinds.txt @@ -1,66 +1,6 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -LCtrl "+Fire" -RCtrl "+Fire" -LShift "+Run" -RShift "+Run" -Capslock "+AutoRun" -A "+Jump" -KP- "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -PgDn "+Look_Down" -, "+Strafe_Left" -KP7 "+Strafe_Left" -. "+Strafe_Right" -KP9 "+Strafe_Right" -Home "+Aim_Up" -End "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" M "+MedKit" -S "+Smoke_Bomb" +B "+Smoke_Bomb" N "+Nightvision" G "+Gas_Bomb" F "+Flash_Bomb" C "+Caltrops" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -= "+Enlarge_Screen" -Scroll "+Holster_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Mouse1 "+Fire" -Mouse2 "+Open" -Mouse3 "+Run" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/shadowwarrior/demolition/origbinds.txt b/wadsrc/static/filter/shadowwarrior/demolition/origbinds.txt index b4c02a99e..91c5b3eef 100644 --- a/wadsrc/static/filter/shadowwarrior/demolition/origbinds.txt +++ b/wadsrc/static/filter/shadowwarrior/demolition/origbinds.txt @@ -1,70 +1,7 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -LCtrl "+Fire" -RCtrl "+Fire" -LShift "+Run" -RShift "+Run" -Capslock "+AutoRun" -A "+Jump" -/ "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -, "+Strafe_Left" -. "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" M "+MedKit" S "+Smoke_Bomb" N "+Nightvision" G "+Gas_Bomb" F "+Flash_Bomb" C "+Caltrops" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Mouse1 "+Fire" Mouse2 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/ww2gi/demolition/defbinds.txt b/wadsrc/static/filter/ww2gi/demolition/defbinds.txt index c42bb1742..04f510ffb 100644 --- a/wadsrc/static/filter/ww2gi/demolition/defbinds.txt +++ b/wadsrc/static/filter/ww2gi/demolition/defbinds.txt @@ -1,77 +1,11 @@ -W "+Move_Forward" -KP8 "+Move_Forward" -S "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -RCtrl "+Fire" -E "+Open" -LShift "+Run" -RShift "+Run" -Space "+Jump" -/ "+Jump" -LCtrl "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -A "+Strafe_Left" -D "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +// +R "+Steroids" +Q "+Quick_Kick" H "+Holo_Duke" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -Y "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -R "+Steroids" -Q "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Capslock "+AutoRun" X "+Last_Used_Weapon" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" C "+Toggle_Crouch" -Mouse1 "+Fire" Mouse2 "+Jetpack" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/ww2gi/demolition/graphics/M_BACK.png b/wadsrc/static/filter/ww2gi/demolition/graphics/M_BACK.png new file mode 100644 index 000000000..32e49b863 Binary files /dev/null and b/wadsrc/static/filter/ww2gi/demolition/graphics/M_BACK.png differ diff --git a/wadsrc/static/filter/ww2gi/demolition/leftbinds.txt b/wadsrc/static/filter/ww2gi/demolition/leftbinds.txt index 83e14ed3e..953ecd791 100644 --- a/wadsrc/static/filter/ww2gi/demolition/leftbinds.txt +++ b/wadsrc/static/filter/ww2gi/demolition/leftbinds.txt @@ -1,76 +1,7 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -LCtrl "+Fire" -RCtrl "+Fire" -LShift "+Run" -RShift "+Run" -A "+Jump" -KP- "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -KP7 "+Strafe_Left" -. "+Strafe_Right" -KP9 "+Strafe_Right" -Home "+Aim_Up" -End "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" H "+Holo_Duke" +R "+Steroids" +Q "+Quick_Kick" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -= "+Enlarge_Screen" -Scroll "+Holster_Weapon" W "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -R "+Steroids" -Q "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" -` "toggleconsole" -Capslock "+AutoRun" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" -Mouse2 "+Open" -Mouse3 "+Run" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" diff --git a/wadsrc/static/filter/ww2gi/demolition/origbinds.txt b/wadsrc/static/filter/ww2gi/demolition/origbinds.txt index 07b541143..62770c115 100644 --- a/wadsrc/static/filter/ww2gi/demolition/origbinds.txt +++ b/wadsrc/static/filter/ww2gi/demolition/origbinds.txt @@ -1,79 +1,13 @@ -uparrow "+Move_Forward" -KP8 "+Move_Forward" -downarrow "+Move_Backward" -KP2 "+Move_Backward" -leftarrow "+Turn_Left" -KP4 "+Turn_Left" -rightarrow "+Turn_Right" -KP6 "+Turn_Right" -LAlt "+Strafe" -RAlt "+Strafe" -LCtrl "+Fire" -RCtrl "+Fire" -LCtrl "+Fire" -RCtrl "+Fire" -LShift "+Run" -RShift "+Run" -A "+Jump" -/ "+Jump" -Z "+Crouch" -PgUp "+Look_Up" -KP9 "+Look_Up" -PgDn "+Look_Down" -KP3 "+Look_Down" -Ins "+Look_Left" -KP0 "+Look_Left" -Del "+Look_Right" -KP. "+Look_Right" -, "+Strafe_Left" -. "+Strafe_Right" -Home "+Aim_Up" -KP7 "+Aim_Up" -End "+Aim_Down" -KP1 "+Aim_Down" -1 "+Weapon_1" -2 "+Weapon_2" -3 "+Weapon_3" -4 "+Weapon_4" -5 "+Weapon_5" -6 "+Weapon_6" -7 "+Weapon_7" -8 "+Weapon_8" -9 "+Weapon_9" -0 "+Weapon_10" -Enter "+Inventory" -KP-Enter "+Inventory" -[ "+Inventory_Left" -] "+Inventory_Right" +// +R "+Steroids" +` "+Quick_Kick" +W "+Show_Opponents_Weapon" H "+Holo_Duke" J "+Jetpack" N "+NightVision" M "+MedKit" -Backspace "+Turn_Around" -T "+Send_Message" -Tab "+Map" -- "+Shrink_Screen" -KP- "+Shrink_Screen" -= "+Enlarge_Screen" -KP+ "+Enlarge_Screen" -KP5 "+Center_View" -Scroll "+Holster_Weapon" -W "+Show_Opponents_Weapon" -F "+Map_Follow_Mode" -K "+See_Coop_View" -U "+Mouse_Aiming" -I "+Toggle_Crosshair" -R "+Steroids" -` "+Quick_Kick" -' "+Next_Weapon" -; "+Previous_Weapon" C "toggleconsole" -Capslock "+AutoRun" -F6 "+Quick_Save" -F9 "+Quick_Load" -F7 "+Third_Person_View" -Mouse1 "+Fire" Mouse2 "+Jetpack" Mouse3 "+MediKit" -MWheelUp "+Previous_Weapon" -MWheelDown "+Next_Weapon" + + \ No newline at end of file diff --git a/wadsrc/static/fonts/consolefont/0000.png b/wadsrc/static/fonts/consolefont/0000.png new file mode 100644 index 000000000..aa78736f7 Binary files /dev/null and b/wadsrc/static/fonts/consolefont/0000.png differ diff --git a/wadsrc/static/fonts/consolefont/0100.png b/wadsrc/static/fonts/consolefont/0100.png new file mode 100644 index 000000000..82a22799e Binary files /dev/null and b/wadsrc/static/fonts/consolefont/0100.png differ diff --git a/wadsrc/static/fonts/consolefont/0400.png b/wadsrc/static/fonts/consolefont/0400.png new file mode 100644 index 000000000..a1f00c3d7 Binary files /dev/null and b/wadsrc/static/fonts/consolefont/0400.png differ diff --git a/wadsrc/static/fonts/consolefont/font.inf b/wadsrc/static/fonts/consolefont/font.inf new file mode 100644 index 000000000..897845b49 --- /dev/null +++ b/wadsrc/static/fonts/consolefont/font.inf @@ -0,0 +1,3 @@ +TranslationType Console +CellSize 8, 8 // This implies font sheets +