note description: "[ m_menu.c DOOM selection menu, options, episodes etc. Sliders and icons. Kinda widget stuff. ]" license: "[ Copyright (C) 1993-1996 by id Software, Inc. Copyright (C) 2005-2014 Simon Howard Copyright (C) 2021 Ilgiz Mustafin 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. ]" class M_MENU create make feature i_main: I_MAIN make (a_i_main: like i_main) do i_main := a_i_main messagestring := "" itemon := 1 end feature -- defaulted values mousesensitivity: INTEGER_32 assign set_mousesensitivity -- has default set_mousesensitivity (a_mousesensitivity: like mousesensitivity) do mousesensitivity := a_mousesensitivity end showmessages: INTEGER_32 assign set_showmessages -- Show messages has default, 0 = off, 1 = on set_showmessages (a_showmessages: like showmessages) do showmessages := a_showmessages end detaillevel: INTEGER_32 assign set_screenblocks -- Blocky mode, has default, 0 = high, 1 = normal set_detaillevel (a_detaillevel: like detaillevel) do detaillevel := a_detaillevel end screenblocks: INTEGER_32 assign set_screenblocks set_screenblocks (a_screenblocks: like screenblocks) do screenblocks := a_screenblocks end feature Lineheight: INTEGER_32 = 16 Skullxoff: INTEGER_32 = -32 Skullname: ARRAY [STRING_8] once create Result.make_filled ("", 0, 1) Result [0] := "M_SKULL1" Result [1] := "M_SKULL2" end feature -- main_e Newgame: INTEGER_32 = 0 Options: INTEGER_32 = 1 Loadgame: INTEGER_32 = 2 Savegame: INTEGER_32 = 3 Readthis: INTEGER_32 = 4 Quitdoom: INTEGER_32 = 5 Main_end: INTEGER_32 = 6 feature -- newgame_e Killthings: INTEGER_32 = 0 Toorough: INTEGER_32 = 1 Hurtme: INTEGER_32 = 2 Violence: INTEGER_32 = 3 Nightmare: INTEGER_32 = 4 Newg_end: INTEGER_32 = 5 feature currentmenu: detachable MENU_T Maindef: MENU_T once create Result.make (Main_end, Void, Mainmenu, agent m_drawmainmenu, 97, 64, 1) end Newgamemenu: ARRAY [MENUITEM_T] once Result := <<create {MENUITEM_T}.make (1, "M_JKILL", agent m_chooseskill, 'i'), create {MENUITEM_T}.make (1, "M_ROUGH", agent m_chooseskill, 'h'), create {MENUITEM_T}.make (1, "M_HURT", agent m_chooseskill, 'h'), create {MENUITEM_T}.make (1, "M_ULTRA", agent m_chooseskill, 'u'), create {MENUITEM_T}.make (1, "M_NMARE", agent m_chooseskill, 'n')>> end Newdef: MENU_T once create Result.make (Newg_end, Epidef, Newgamemenu, agent m_drawnewgame, 48, 63, Hurtme + 1) end Mainmenu: ARRAY [MENUITEM_T] once Result := <<create {MENUITEM_T}.make (1, "M_NGAME", agent m_newgame, 'n'), create {MENUITEM_T}.make (1, "M_OPTION", agent m_options, 'o'), create {MENUITEM_T}.make (1, "M_LOADG", agent m_loadgame, 'l'), create {MENUITEM_T}.make (1, "M_SAVEG", agent m_savegame, 's'), create {MENUITEM_T}.make (1, "M_RDTHIS", agent m_readthis, 'r'), create {MENUITEM_T}.make (1, "M_QUITG", agent m_quitdoom, 'q')>> end inhelpscreens: BOOLEAN menuactive: BOOLEAN itemon: INTEGER_32 -- menu item skull is on whichskull: INTEGER_32 -- which skull to draw skullanimcounter: INTEGER_32 -- skull animation counter screensize: INTEGER_32 -- temp for screenblocks (0-9) messagetoprint: BOOLEAN -- (was int) 1 = message to be printed messagestring: STRING_8 -- ...and here is the message string! messagelastmenuactive: BOOLEAN -- (was int) messageroutine: detachable PROCEDURE [INTEGER_32] messageneedsinput: BOOLEAN -- timed message = no input from user quicksaveslot: INTEGER_32 -- -1 = no quicksave slot picked! feature -- Read This! MENU 1 & 2 Rdthssempty1: INTEGER_32 = 0 Read1_end: INTEGER_32 = 1 Readmenu1: ARRAY [MENUITEM_T] once Result := <<create {MENUITEM_T}.make (1, "", agent m_readthis2, '0')>> end Readdef1: MENU_T once create Result.make (Read1_end, Maindef, Readmenu1, agent m_drawreadthis1, 280, 185, 1) end Rdthsempty2: INTEGER_32 = 0 Read2_end: INTEGER_32 = 1 Readmenu2: ARRAY [MENUITEM_T] once Result := <<create {MENUITEM_T}.make (1, "", agent m_finishreadthis, '0')>> end Readdef2: MENU_T once create Result.make (Read2_end, Readdef1, Readmenu2, agent m_drawreadthis2, 330, 175, 0) end feature -- Read This Menus (Had a "quick hack to fix romero bug") m_drawreadthis1 local gamemode: GAME_MODE_T do inhelpscreens := True gamemode := i_main.Doomstat_h.gamemode if gamemode = {GAME_MODE_T}.commercial then i_main.V_video.v_drawpatchdirect (0, 0, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname ("HELP"))) elseif gamemode = {GAME_MODE_T}.shareware or gamemode = {GAME_MODE_T}.registered or gamemode = {GAME_MODE_T}.retail then i_main.V_video.v_drawpatchdirect (0, 0, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname ("HELP1"))) end end m_drawreadthis2 local gamemode: GAME_MODE_T do inhelpscreens := True gamemode := i_main.Doomstat_h.gamemode if gamemode = {GAME_MODE_T}.retail or gamemode = {GAME_MODE_T}.commercial then i_main.V_video.v_drawpatchdirect (0, 0, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname ("CREDIT"))) elseif gamemode = {GAME_MODE_T}.shareware or gamemode = {GAME_MODE_T}.registered then i_main.V_video.v_drawpatchdirect (0, 0, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname ("HELP2"))) end end feature m_finishreadthis (choice: INTEGER_32) do {NOT_IMPLEMENTED}.not_implemented ("M_FinishReadThis", False) end m_drawepisode do i_main.V_video.v_drawpatchdirect (54, 38, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname ("M_EPISOD"))) end m_readthis2 (choice: INTEGER_32) do {NOT_IMPLEMENTED}.not_implemented ("M_ReadThis2", False) end m_newgame (choice: INTEGER_32) do if i_main.G_game.netgame and not i_main.G_game.demoplayback then m_startmessage ({D_ENGLSH}.newgame, Void, False) else if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial then m_setupnextmenu (Newdef) else m_setupnextmenu (Epidef) end end end m_options (choice: INTEGER_32) do {NOT_IMPLEMENTED}.not_implemented ("M_Options", False) end m_loadgame (choice: INTEGER_32) do {NOT_IMPLEMENTED}.not_implemented ("M_LoadGame", False) end m_savegame (choice: INTEGER_32) do {NOT_IMPLEMENTED}.not_implemented ("M_SaveGame", False) end m_readthis (choice: INTEGER_32) do {NOT_IMPLEMENTED}.not_implemented ("M_ReadThis", False) end m_quitdoom (choice: INTEGER_32) do {NOT_IMPLEMENTED}.not_implemented ("M_QuitDOOM", False) i_main.I_system.i_quit end m_drawnewgame do i_main.V_video.v_drawpatchdirect (96, 14, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname ("M_NEWG"))) i_main.V_video.v_drawpatchdirect (54, 38, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname ("M_SKILL"))) end m_chooseskill (a_choice: INTEGER_32) local choice: INTEGER_32 do choice := a_choice - 1 if choice = Nightmare then m_startmessage ({D_ENGLSH}.nightmare, agent m_verifynightmare, True) else i_main.G_game.g_deferedinitnew (choice, epi + 1, 1) m_clearmenus end end m_verifynightmare (ch: INTEGER_32) do if ch = ('y').code then i_main.G_game.g_deferedinitnew (Nightmare, epi + 1, 1) m_clearmenus end end m_drawmainmenu do i_main.V_video.v_drawpatchdirect (94, 2, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname ("M_DOOM"))) end feature m_clearmenus do menuactive := False end feature m_startmessage (string: STRING_8; routine: like messageroutine; input: BOOLEAN) do messagelastmenuactive := menuactive messagetoprint := True messagestring := string messageroutine := routine messageneedsinput := input menuactive := True end feature m_setupnextmenu (menudef: MENU_T) do currentmenu := menudef itemon := menudef.laston end feature -- EPISODE SELECT Ep1: INTEGER_32 = 0 Ep2: INTEGER_32 = 1 Ep3: INTEGER_32 = 2 Ep4: INTEGER_32 = 3 Ep_end: INTEGER_32 = 4 Episodemenu: ARRAY [MENUITEM_T] once Result := <<create {MENUITEM_T}.make (1, "M_EPI1", agent m_episode, 'k'), create {MENUITEM_T}.make (1, "M_EPI2", agent m_episode, 't'), create {MENUITEM_T}.make (1, "M_EPI3", agent m_episode, 'i'), create {MENUITEM_T}.make (1, "M_EPI4", agent m_episode, 't')>> end Epidef: MENU_T once create Result.make (Ep_end, Maindef, Episodemenu, agent m_drawepisode, 48, 63, 1) end feature -- M_Episode epi: INTEGER_32 m_episode (a_choice: INTEGER_32) local choice: INTEGER_32 do choice := a_choice - 1 if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.shareware and choice /= 0 then m_startmessage ({D_ENGLSH}.swstring, Void, False) m_setupnextmenu (Readdef1) else if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.registered and choice > 2 then print ("M_Episode: 4th episode requires UltimateDOOM%N") choice := 0 end epi := choice m_setupnextmenu (Newdef) end end feature savestringenter: BOOLEAN -- we are going to be entering a savegame string feature -- CONTROL PANEL m_responder (ev: EVENT_T): BOOLEAN local ch: INTEGER_32 do {NOT_IMPLEMENTED}.not_implemented ("M_Responder", False) if ev.type = ev.Ev_quit then i_main.S_sound.s_startsound (Void, {SOUNDS_H}.sfx_swtchn) m_quitdoom (0) end ch := -1 if ev.type = ev.Ev_keydown then ch := ev.data1 end if ch /= -1 then if savestringenter then elseif messagetoprint then elseif False then elseif not menuactive then if ch = {DOOMDEF_H}.key_escape then m_startcontrolpanel i_main.S_sound.s_startsound (Void, {SOUNDS_H}.sfx_swtchn) Result := True else Result := False end else if attached currentmenu as currentmenuattached then if ch = {DOOMDEF_H}.key_downarrow then from if itemon >= currentmenuattached.numitems then itemon := 1 else itemon := itemon + 1 end i_main.S_sound.s_startsound (Void, {SOUNDS_H}.sfx_pstop) until currentmenuattached.menuitems [itemon].status /= -1 loop if itemon + 1 > currentmenuattached.numitems - 1 then itemon := 0 else itemon := itemon + 1 end i_main.S_sound.s_startsound (Void, {SOUNDS_H}.sfx_pstop) end Result := True elseif ch = {DOOMDEF_H}.key_uparrow then from if itemon = 1 then itemon := currentmenuattached.numitems else itemon := itemon - 1 end i_main.S_sound.s_startsound (Void, {SOUNDS_H}.sfx_pstop) until currentmenuattached.menuitems [itemon].status /= -1 loop if itemon = 0 then itemon := currentmenuattached.numitems - 1 else itemon := itemon - 1 end i_main.S_sound.s_startsound (Void, {SOUNDS_H}.sfx_pstop) end Result := True elseif ch = {DOOMDEF_H}.key_enter then if currentmenuattached.menuitems [itemon].status /= 0 then currentmenuattached.laston := itemon if currentmenuattached.menuitems [itemon].status = 2 then currentmenuattached.menuitems [itemon].routine.call (1) i_main.S_sound.s_startsound (Void, {SOUNDS_H}.sfx_stnmov) else currentmenuattached.menuitems [itemon].routine (itemon) i_main.S_sound.s_startsound (Void, {SOUNDS_H}.sfx_pistol) end end end end end end end feature m_init do currentmenu := Maindef menuactive := False if attached currentmenu as c then itemon := c.laston end whichskull := 0 skullanimcounter := 10 screensize := screenblocks - 3 messagetoprint := False messagelastmenuactive := menuactive quicksaveslot := -1 if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial then Mainmenu [Readthis] := Mainmenu [Quitdoom] Maindef.numitems := Maindef.numitems - 1 Maindef.y := Maindef.y + 8 Newdef.prevmenu := Maindef Readdef1.routine := agent m_drawreadthis1 Readdef1.x := 330 Readdef1.y := 165 Readmenu1 [0].routine := agent m_finishreadthis elseif i_main.Doomstat_h.gamemode = {GAME_MODE_T}.shareware then Epidef.numitems := Epidef.numitems - 1 elseif i_main.Doomstat_h.gamemode = {GAME_MODE_T}.registered then Epidef.numitems := Epidef.numitems - 1 end end feature m_ticker do skullanimcounter := skullanimcounter - 1 if skullanimcounter <= 0 then whichskull := whichskull.bit_xor (1) skullanimcounter := 8 end end feature -- M_Drawer x: INTEGER_32 y: INTEGER_32 m_drawer -- Called after the view has been rendered, -- but before it has been blitted. local i: INTEGER_32 max: INTEGER_32 do {NOT_IMPLEMENTED}.not_implemented ("M_Drawer", False) inhelpscreens := False if messagetoprint then elseif not menuactive then else if attached currentmenu as cm then if attached cm.routine as r then r.call end x := cm.x y := cm.y max := cm.numitems from i := 1 until i > cm.numitems loop if not cm.menuitems [i].name.is_empty then i_main.V_video.v_drawpatchdirect (x, y, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname (cm.menuitems [i].name))) end y := y + Lineheight i := i + 1 end i_main.V_video.v_drawpatchdirect (x + Skullxoff, cm.y - 5 + (itemon - 1) * Lineheight, create {PATCH_T}.from_pointer (i_main.W_wad.w_cachelumpname (Skullname [whichskull]))) end end end feature m_startcontrolpanel do if menuactive then else menuactive := True currentmenu := Maindef itemon := Maindef.laston end end invariant itemon >= 1 attached currentmenu as i_cm implies itemon <= i_cm.numitems end -- class M_MENU
Generated by ISE EiffelStudio