note description: "[ g_game.c none ]" 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 G_GAME inherit DOOMDEF_H WEAPONTYPE_T AMMOTYPE_T create make feature i_main: I_MAIN make (a_i_main: like i_main) do i_main := a_i_main create wminfo pars := <<<<30, 75, 120, 90, 165, 180, 180, 30, 165>>, <<90, 90, 90, 120, 90, 360, 240, 30, 170>>, <<90, 45, 90, 150, 90, 90, 165, 30, 135>>>> cpars := <<30, 90, 120, 120, 90, 150, 120, 120, 270, 90, 210, 150, 150, 150, 210, 150, 420, 150, 210, 150, 240, 150, 180, 150, 150, 300, 330, 420, 300, 180, 120, 30>> cpars.rebase (0) precache := True end feature Turbothreshold: INTEGER_32 = 50 feature nodrawers: BOOLEAN -- for comparative timing purposes noblit: BOOLEAN -- for comparative timing purposes timingdemo: BOOLEAN -- if true, exit with report on completion feature viewactive: BOOLEAN singledemo: BOOLEAN -- quit after playing a demo from cmdline precache: BOOLEAN demoname: detachable STRING_8 demoplayback: BOOLEAN demobuffer: detachable DEMOLUMP_T -- originally byte* feature paused: BOOLEAN assign set_paused set_paused (a_paused: like paused) do paused := a_paused end sendpause: BOOLEAN -- send a pause event next tic sendsave: BOOLEAN -- send a save event next tic usergame: BOOLEAN assign set_usergame -- ok to save / end game set_usergame (a_usergame: like usergame) do usergame := a_usergame end feature bodyqueslot: INTEGER_32 assign set_bodyqueslot set_bodyqueslot (a_bodyqueslot: like bodyqueslot) do bodyqueslot := a_bodyqueslot end feature levelstarttic: INTEGER_32 -- gametic at level start starttime: INTEGER_32 -- for comparative timing puroses totalkills: INTEGER_32 assign set_totalkills set_totalkills (a_totalkills: like totalkills) do totalkills := a_totalkills end totalitems: INTEGER_32 assign set_totalitems set_totalitems (a_totalitems: like totalitems) do totalitems := a_totalitems end totalsecret: INTEGER_32 assign set_totalsecret set_totalsecret (a_totalsecret: like totalsecret) do totalsecret := a_totalsecret end wminfo: WBSTARTSTRUCT_T feature -- controls (have defaults) key_right: INTEGER_32 assign set_key_right set_key_right (a_key_right: like key_right) do key_right := a_key_right end key_left: INTEGER_32 assign set_key_left set_key_left (a_key_left: like key_left) do key_left := a_key_left end key_up: INTEGER_32 assign set_key_up set_key_up (a_key_up: like key_up) do key_up := a_key_up end key_down: INTEGER_32 assign set_key_down set_key_down (a_key_down: like key_down) do key_down := a_key_down end key_strafeleft: INTEGER_32 assign set_key_strafeleft set_key_strafeleft (a_key_strafeleft: like key_strafeleft) do key_strafeleft := a_key_strafeleft end key_straferight: INTEGER_32 assign set_key_straferight set_key_straferight (a_key_straferight: like key_straferight) do key_straferight := a_key_straferight end key_fire: INTEGER_32 assign set_key_fire set_key_fire (a_key_fire: like key_fire) do key_fire := a_key_fire end key_use: INTEGER_32 assign set_key_use set_key_use (a_key_use: like key_use) do key_use := a_key_use end key_debug_a: INTEGER_32 assign set_key_debug_a -- DEBUG set_key_debug_a (a_key_debug_a: like key_debug_a) do key_debug_a := a_key_debug_a end key_debug_b: INTEGER_32 assign set_key_debug_b -- DEBUG set_key_debug_b (a_key_debug_b: like key_debug_b) do key_debug_b := a_key_debug_b end key_strafe: INTEGER_32 assign set_key_strafe set_key_strafe (a_key_strafe: like key_strafe) do key_strafe := a_key_strafe end key_speed: INTEGER_32 assign set_key_speed set_key_speed (a_key_speed: like key_speed) do key_speed := a_key_speed end mousebfire: INTEGER_32 assign set_mousebfire set_mousebfire (a_mousebfire: like mousebfire) do mousebfire := a_mousebfire end mousebstrafe: INTEGER_32 assign set_mousebstrafe set_mousebstrafe (a_mousebstrafe: like mousebstrafe) do mousebstrafe := a_mousebstrafe end mousebforward: INTEGER_32 assign set_mousebforward set_mousebforward (a_mousebforward: like mousebforward) do mousebforward := a_mousebforward end joybfire: INTEGER_32 assign set_joybfire set_joybfire (a_joybfire: like joybfire) do joybfire := a_joybfire end joybstrafe: INTEGER_32 assign set_joybstrafe set_joybstrafe (a_joybstrafe: like joybstrafe) do joybstrafe := a_joybstrafe end joybuse: INTEGER_32 assign set_joybuse set_joybuse (a_joybuse: like joybuse) do joybuse := a_joybuse end joybspeed: INTEGER_32 assign set_joybspeed set_joybspeed (a_joybspeed: like joybspeed) do joybspeed := a_joybspeed end Maxplmove: INTEGER_32 once Result := Forwardmove [1] end Mousebuttons: ARRAY [BOOLEAN] -- originally &mousearray[1] with boolean mousearray[4] once create Result.make_filled (False, -1, {I_INPUT}.max_mouse_buttons - 1) end mousex: INTEGER_32 mousey: INTEGER_32 dclicktime: INTEGER_32 dclickstate: BOOLEAN -- originally int dclicks: INTEGER_32 dclicktime2: INTEGER_32 dclickstate2: BOOLEAN -- originally int dclicks2: INTEGER_32 -- joystick values are repeated joyxmove: INTEGER_32 joyymove: INTEGER_32 Joybuttons: ARRAY [BOOLEAN] -- originall &joyarray[1] with boolean joyarray[5] once create Result.make_filled (False, -1, 3) end savegameslot: INTEGER_32 savedescription: detachable STRING_8 turnheld: INTEGER_32 Slowturntics: INTEGER_32 = 6 Forwardmove: ARRAY [INTEGER_32] once create Result.make_filled (0, 0, 1) Result [0] := 25 Result [1] := 50 ensure Result.lower = 0 and Result.count = 2 end Sidemove: ARRAY [INTEGER_32] once create Result.make_filled (0, 0, 1) Result [0] := 24 Result [1] := 40 ensure Result.lower = 0 and Result.count = 2 end Angleturn: ARRAY [INTEGER_32] -- + slow turn once create Result.make_filled (0, 0, 2) Result [0] := 640 Result [1] := 1280 Result [2] := 320 ensure Result.lower = 0 and Result.count = 3 end feature Consistancy: ARRAY [ARRAY [INTEGER_32]] local i: INTEGER_32 once create Result.make_filled (create {ARRAY [INTEGER_32]}.make_empty, 0, {DOOMDEF_H}.maxplayers - 1) from i := 0 until i >= {DOOMDEF_H}.maxplayers loop Result [i] := create {ARRAY [INTEGER_32]}.make_filled (0, 0, {D_NET}.backuptics - 1) i := i + 1 end end Numkeys: INTEGER_32 = 256 Gamekeydown: ARRAY [BOOLEAN] once create Result.make_filled (False, 0, Numkeys - 1) end feature -- gameaction_t Ga_nothing: INTEGER_32 = 0 Ga_loadlevel: INTEGER_32 = 1 Ga_newgame: INTEGER_32 = 2 Ga_loadgame: INTEGER_32 = 3 Ga_savegame: INTEGER_32 = 4 Ga_playdemo: INTEGER_32 = 5 Ga_completed: INTEGER_32 = 6 Ga_victory: INTEGER_32 = 7 Ga_worlddone: INTEGER_32 = 8 Ga_screenshot: INTEGER_32 = 9 feature gameaction: INTEGER_32 assign set_gameaction set_gameaction (a_gameaction: like gameaction) do gameaction := a_gameaction end gamestate: INTEGER_32 assign set_gamestate set_gamestate (a_gamestate: like gamestate) do gamestate := a_gamestate end gameskill: INTEGER_32 gameepisode: INTEGER_32 gamemap: INTEGER_32 respawnmonsters: BOOLEAN feature demorecording: BOOLEAN netgame: BOOLEAN assign set_netgame set_netgame (a_netgame: like netgame) do netgame := a_netgame end deathmatch: BOOLEAN -- only if started as net death netdemo: BOOLEAN feature -- G_InitNew d_skill: INTEGER_32 d_episode: INTEGER_32 d_map: INTEGER_32 g_deferedinitnew (skill, episode, map: INTEGER_32) do d_skill := skill d_episode := episode d_map := map gameaction := Ga_newgame end g_initnew (a_skill: INTEGER_32; a_episode: INTEGER_32; a_map: INTEGER_32) local i: INTEGER_32 skill: INTEGER_32 episode: INTEGER_32 map: INTEGER_32 do skill := a_skill episode := a_episode map := a_map if paused then paused := False i_main.S_sound.s_resumesound end if skill > Sk_nightmare then skill := Sk_nightmare end if episode < 1 then episode := 1 end if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.retail then if episode > 4 then episode := 4 end elseif i_main.Doomstat_h.gamemode = {GAME_MODE_T}.shareware then if episode > 1 then episode := 1 end else if episode > 3 then episode := 3 end end if map < 1 then map := 1 end if map > 9 and i_main.Doomstat_h.gamemode /= {GAME_MODE_T}.commercial then map := 9 end i_main.M_random.m_clearrandom check attached i_main.D_main as main then if skill = Sk_nightmare or main.respawnparm then respawnmonsters := True else respawnmonsters := False end if main.fastparm or (skill = Sk_nightmare and gameskill /= Sk_nightmare) then from i := {INFO}.s_sarg_run1 until i > {INFO}.s_sarg_pain2 loop {INFO}.states [i].tics := {INFO}.states [i].tics |>> 1 i := i + 1 end {INFO}.mobjinfo [{INFO}.mt_bruisershot].speed := 20 * {M_FIXED}.fracunit {INFO}.mobjinfo [{INFO}.mt_headshot].speed := 20 * {M_FIXED}.fracunit {INFO}.mobjinfo [{INFO}.mt_troopshot].speed := 20 * {M_FIXED}.fracunit elseif skill /= Sk_nightmare and gameskill = Sk_nightmare then from i := {INFO}.s_sarg_run1 until i > {INFO}.s_sarg_pain2 loop {INFO}.states [i].tics := {INFO}.states [i].tics |<< 1 i := i + 1 end {INFO}.mobjinfo [{INFO}.mt_bruisershot].speed := 15 * {M_FIXED}.fracunit {INFO}.mobjinfo [{INFO}.mt_headshot].speed := 10 * {M_FIXED}.fracunit {INFO}.mobjinfo [{INFO}.mt_troopshot].speed := 10 * {M_FIXED}.fracunit end end from i := 0 until i >= Maxplayers loop Players [i].playerstate := {D_PLAYER}.pst_reborn i := i + 1 end usergame := True paused := False demoplayback := False i_main.Am_map.automapactive := False viewactive := True gameepisode := episode gamemap := map gameskill := skill viewactive := True if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial then i_main.R_sky.skytexture := i_main.R_data.r_texturenumforname ("SKY3") if gamemap < 12 then i_main.R_sky.skytexture := i_main.R_data.r_texturenumforname ("SKY1") elseif gamemap < 21 then i_main.R_sky.skytexture := i_main.R_data.r_texturenumforname ("SKY2") end else i_main.R_sky.skytexture := i_main.R_data.r_texturenumforname ("SKY" + episode.out) end g_doloadlevel end feature -- G_DoCompleted secretexit: BOOLEAN g_exitlevel do secretexit := False gameaction := Ga_completed end g_secretexitlevel -- Here's for the german edition do if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial and i_main.W_wad.w_checknumforname ("map31") < 0 then secretexit := False else secretexit := True gameaction := Ga_completed end end feature consoleplayer: INTEGER_32 assign set_consoleplayer -- player taking events and displaying displayplayer: INTEGER_32 assign set_displayplayer -- view being displayed gametic: INTEGER_32 assign set_gametic feature set_gametic (a_gametic: like gametic) do gametic := a_gametic end set_consoleplayer (a_consoleplayer: like consoleplayer) do consoleplayer := a_consoleplayer end set_displayplayer (a_displayplayer: like displayplayer) do displayplayer := a_displayplayer end feature g_beginrecording require attached demobuffer local i: INTEGER_32 do check attached demobuffer as db then db.version := {DOOMDEF_H}.version.to_natural_8.to_integer_32 db.skill := gameskill db.episode := gameepisode db.map := gamemap db.deathmatch := deathmatch db.respawnparm := i_main.D_main.respawnparm db.fastparm := i_main.D_main.fastparm db.nomonsters := i_main.D_main.nomonsters db.consoleplayer := consoleplayer db.playeringame := Playeringame.twin end end debug_a do if attached Players [consoleplayer].mo as mo then print ("DEBUG_A: player.mo (" + mo.x.out + " " + mo.y.out + " " + mo.z.out + " " + mo.angle.out + ")%N") else print ("DEBUG_A: player.mo is Void%N") end end debug_b do g_exitlevel end g_buildticcmd (cmd: TICCMD_T) -- Builds a ticcmd from all of the available inputs -- or reads it from the demo buffer. -- If recording a demo, write it out local i: INTEGER_32 done: BOOLEAN strafe: BOOLEAN bstrafe: BOOLEAN speed: INTEGER_32 tspeed: INTEGER_32 forward: INTEGER_32 side: INTEGER_32 base: TICCMD_T do base := i_main.I_system.I_baseticcmd cmd.copy_from (base) cmd.consistancy := Consistancy [consoleplayer] [i_main.D_net.maketic \\ {D_NET}.backuptics] if Gamekeydown [key_debug_a] then debug_a end if Gamekeydown [key_debug_b] then debug_b end strafe := Gamekeydown [key_strafe] or Mousebuttons [mousebstrafe] or Joybuttons [joybstrafe] speed := if Gamekeydown [key_speed] or Joybuttons [joybspeed] then 1 else 0 end forward := 0 side := 0 if joyxmove < 0 or joyxmove > 0 or Gamekeydown [key_right] or Gamekeydown [key_left] then turnheld := turnheld + i_main.D_net.ticdup else turnheld := 0 end if turnheld < Slowturntics then tspeed := 2 else tspeed := speed end if strafe then if Gamekeydown [key_right] then side := side + Sidemove [speed] end if Gamekeydown [key_left] then side := side - Sidemove [speed] end if joyxmove > 0 then side := side + Sidemove [speed] end if joyxmove < 0 then side := side - Sidemove [speed] end else if Gamekeydown [key_right] then cmd.angleturn := cmd.angleturn - Angleturn [tspeed] end if Gamekeydown [key_left] then cmd.angleturn := cmd.angleturn + Angleturn [tspeed] end if joyxmove > 0 then cmd.angleturn := cmd.angleturn - Angleturn [tspeed] end if joyxmove < 0 then cmd.angleturn := cmd.angleturn + Angleturn [tspeed] end end if Gamekeydown [key_up] then forward := forward + Forwardmove [speed] end if Gamekeydown [key_down] then forward := forward - Forwardmove [speed] end if joyymove < 0 then forward := forward + Forwardmove [speed] end if joyymove > 0 then forward := forward - Forwardmove [speed] end if Gamekeydown [key_straferight] then side := side + Sidemove [speed] end if Gamekeydown [key_strafeleft] then side := side - Sidemove [speed] end cmd.chatchar := i_main.Hu_stuff.hu_dequeuechatchar if Gamekeydown [key_fire] or Mousebuttons [mousebfire] or Joybuttons [joybfire] then cmd.buttons := cmd.buttons | {D_EVENT}.bt_attack end if Gamekeydown [key_use] or Joybuttons [joybuse] then cmd.buttons := cmd.buttons | {D_EVENT}.bt_use dclicks := 0 end from i := 0 done := False until done or i >= Numweapons - 1 loop if Gamekeydown [('1').code + i] then cmd.buttons := cmd.buttons | {D_EVENT}.bt_change cmd.buttons := cmd.buttons | (i |<< {D_EVENT}.bt_weaponshift) done := True end i := i + 1 end if Mousebuttons [mousebforward] then forward := forward + Forwardmove [speed] end if Mousebuttons [mousebforward] /= dclickstate and dclicktime > 1 then dclickstate := Mousebuttons [mousebforward] if dclickstate then dclicks := dclicks + 1 end if dclicks = 2 then cmd.buttons := cmd.buttons | {D_EVENT}.bt_use dclicks := 0 else dclicktime := 0 end else dclicktime := dclicktime + i_main.D_net.ticdup if dclicktime > 20 then dclicks := 0 dclickstate := False end end bstrafe := Mousebuttons [mousebstrafe] or Joybuttons [joybstrafe] if bstrafe /= dclickstate2 and dclicktime2 > 1 then dclickstate2 := bstrafe if dclickstate2 then dclicks2 := dclicks2 + 1 end if dclicks2 = 2 then cmd.buttons := cmd.buttons | {D_EVENT}.bt_use dclicks2 := 0 else dclicktime2 := 0 end else dclicktime2 := dclicktime2 + i_main.D_net.ticdup if dclicktime2 > 20 then dclicks2 := 0 dclickstate2 := False end end forward := forward + mousey if strafe then side := side + mousex * 2 else cmd.angleturn := cmd.angleturn - mousex * 8 end mousex := 0 mousey := 0 if forward > Maxplmove then forward := Maxplmove elseif forward < - Maxplmove then forward := - Maxplmove end if side > Maxplmove then side := Maxplmove elseif side < - Maxplmove then side := - Maxplmove end cmd.forwardmove := (cmd.forwardmove.to_integer_32 + forward).to_integer_8 cmd.sidemove := (cmd.sidemove.to_integer_32 + side).to_integer_8 if sendpause then sendpause := False cmd.buttons := {D_EVENT}.bt_special | {D_EVENT}.bts_pause end if sendsave then sendsave := False cmd.buttons := {D_EVENT}.bt_special | {D_EVENT}.bts_savegame | (savegameslot |<< {D_EVENT}.bts_saveshift) end end g_ticker -- Make ticcmd_ts for the players. local i: INTEGER_32 buf: INTEGER_32 cmd: TICCMD_T btn: INTEGER_32 do from i := 0 until i >= {DOOMDEF_H}.maxplayers loop if Playeringame [i] and Players [i].playerstate = {PLAYER_T}.pst_reborn then g_doreborn (i) end i := i + 1 end from until gameaction = Ga_nothing loop if gameaction = Ga_loadlevel then g_doloadlevel elseif gameaction = Ga_newgame then g_donewgame elseif gameaction = Ga_loadgame then g_doloadgame elseif gameaction = Ga_savegame then g_dosavegame elseif gameaction = Ga_playdemo then g_doplaydemo elseif gameaction = Ga_completed then g_docompleted elseif gameaction = Ga_victory then i_main.F_finale.f_startfinale elseif gameaction = Ga_worlddone then g_doworlddone elseif gameaction = Ga_screenshot then i_main.M_misc.m_screenshot gameaction := Ga_nothing end end buf := (gametic // i_main.D_net.ticdup) \\ {D_NET}.backuptics from i := 0 until i >= Maxplayers loop if Playeringame [i] then cmd := Players [i].cmd cmd.copy (i_main.D_net.Netcmds [i] [buf]) if demoplayback then g_readdemoticcmd (cmd) end if demorecording then g_writedemoticcmd (cmd) end if cmd.forwardmove.to_integer_32 > Turbothreshold and (gametic & 31 /= 0) and ((gametic |>> 5) & 3) = i then Players [consoleplayer].message := {HU_STUFF}.player_names [i] + " is turbo!" end if netgame and not netdemo and gametic \\ i_main.D_net.ticdup = 0 then if gametic > {D_NET}.backuptics and Consistancy [i] [buf] /= cmd.consistancy then {I_MAIN}.i_error ("consistancy failure (" + cmd.consistancy.out + " should be " + Consistancy [i] [buf].out + ")") end if attached Players [i].mo as mo then Consistancy [i] [buf] := mo.x.to_integer_32 else Consistancy [i] [buf] := i_main.M_random.rndindex end end end i := i + 1 end from i := 0 until i >= Maxplayers loop if Playeringame [i] then if Players [i].cmd.buttons & {D_EVENT}.bt_special /= 0 then btn := Players [i].cmd.buttons & {D_EVENT}.bt_specialmask if btn = {D_EVENT}.bts_pause then paused := not paused if paused then i_main.S_sound.s_pausesound else i_main.S_sound.s_resumesound end elseif btn = {D_EVENT}.bts_savegame then if savedescription = Void then savedescription := "NET GAME" end savegameslot := (Players [i].cmd.buttons & {D_EVENT}.bts_savemask) |>> {D_EVENT}.bts_saveshift gameaction := Ga_savegame end end end i := i + 1 end if gamestate = Gs_level then i_main.P_tick.p_ticker i_main.St_stuff.st_ticker i_main.Am_map.am_ticker i_main.Hu_stuff.hu_ticker elseif gamestate = Gs_intermission then i_main.Wi_stuff.wi_ticker elseif gamestate = Gs_finale then i_main.F_finale.f_ticker elseif gamestate = Gs_demoscreen then check attached i_main.D_main as d_doom_main then d_doom_main.d_pageticker end end end feature -- demo g_readdemoticcmd (cmd: TICCMD_T) require attached demobuffer do check attached demobuffer as db then if db.ticks_after then g_checkdemostatus.do_nothing else cmd.copy_from (db.current_tick.to_ticcmd) db.advance_tick end end end g_writedemoticcmd (cmd: TICCMD_T) require attached demobuffer do if Gamekeydown [('q').code] then g_checkdemostatus.do_nothing end check attached demobuffer as db then db.add_tick (create {DEMOTICK_T}.from_ticcmd (cmd)) if db.ticks.count * 4 > db.maxsize - 16 then g_checkdemostatus.do_nothing else g_readdemoticcmd (cmd) end end end g_checkdemostatus: BOOLEAN -- Called after a death or level completion to allow demos to be cleaned up -- Returns true if a new demo loop action will take place require demorecording implies attached demoname and attached demobuffer local endtime: INTEGER_32 p: MANAGED_POINTER_WITH_OFFSET do if timingdemo then endtime := i_main.I_system.i_gettime across i_main.I_timer.perfframes is frame loop print (frame.microseconds.out + "," + frame.description + "%N") end {I_MAIN}.i_error ("timed " + gametic.out + " gametics in " + (endtime - starttime).out + " realtics") end if demoplayback then if singledemo then i_main.I_system.i_quit end demoplayback := False netdemo := False netgame := False deathmatch := False Playeringame [1] := False Playeringame [2] := False Playeringame [3] := False i_main.D_main.respawnparm := False i_main.D_main.fastparm := False i_main.D_main.nomonsters := False consoleplayer := 0 i_main.D_main.d_advancedemo Result := True end if demorecording then check attached demoname as l_demoname and then attached demobuffer as l_demobuffer then i_main.M_misc.m_writefile_managed_pointer (l_demoname, l_demobuffer.to_managed_pointer).do_nothing demobuffer := Void demorecording := False {I_MAIN}.i_error ("Demo " + l_demoname + " recorded") end end end feature -- G_TimeDemo g_timedemo (name: STRING_8) do nodrawers := i_main.m_argv.m_checkparm ("-nodraw").to_boolean noblit := i_main.m_argv.m_checkparm ("-noblit").to_boolean timingdemo := True i_main.D_main.singletics := True defdemoname := name gameaction := Ga_playdemo end feature g_doreborn (playernum: INTEGER_32) do if not netgame then gameaction := Ga_loadlevel else {NOT_IMPLEMENTED}.not_implemented ("G_DoReborn for netgame", True) end end feature -- G_DoLoadLevel wipegamestate: INTEGER_32 g_doloadlevel local i: INTEGER_32 do i_main.R_sky.skyflatnum := i_main.R_data.r_flatnumforname ({R_SKY}.skyflatname) if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial then i_main.R_sky.skytexture := i_main.R_data.r_texturenumforname ("SKY3") if gamemap < 12 then i_main.R_sky.skytexture := i_main.R_data.r_texturenumforname ("SKY1") elseif gamemap < 21 then i_main.R_sky.skytexture := i_main.R_data.r_texturenumforname ("SKY2") end end levelstarttic := gametic if wipegamestate = Gs_level then wipegamestate := -1 end gamestate := Gs_level from i := 0 until i >= Maxplayers loop if Playeringame [i] and then Players [i].playerstate = {D_PLAYER}.pst_dead then Players [i].playerstate := {D_PLAYER}.pst_reborn end; Players [i].frags.fill_with (0) i := i + 1 end i_main.P_setup.p_setuplevel (gameepisode, gamemap, 0, gameskill) displayplayer := consoleplayer starttime := i_main.I_system.i_gettime gameaction := Ga_nothing Gamekeydown.fill_with (False) joyxmove := 0 joyymove := 0 mousex := 0 mousey := 0 sendpause := False sendsave := False paused := False Mousebuttons.fill_with (False) Joybuttons.fill_with (False) end g_donewgame do demoplayback := False netdemo := False netgame := False deathmatch := False Playeringame [1] := False Playeringame [2] := False Playeringame [3] := False check attached i_main.D_main as main then main.respawnparm := False main.fastparm := False main.nomonsters := False end consoleplayer := 0 g_initnew (d_skill, d_episode, d_map) gameaction := Ga_nothing end g_doloadgame do {NOT_IMPLEMENTED}.not_implemented ("G_DoLoadGame", True) end g_dosavegame do {NOT_IMPLEMENTED}.not_implemented ("G_DoSaveGame", True) end g_doplaydemo require attached defdemoname local skill: INTEGER_32 i, episode, map: INTEGER_32 do gameaction := Ga_nothing check attached defdemoname as l_defdemoname then create demobuffer.from_pointer (i_main.W_wad.w_cachelumpname (l_defdemoname)) end check attached demobuffer as l_demobuffer then if l_demobuffer.version /= {DOOMDEF_H}.version then print ("Demo is from a different game version!%N") gameaction := Ga_nothing else skill := l_demobuffer.skill episode := l_demobuffer.episode map := l_demobuffer.map deathmatch := l_demobuffer.deathmatch i_main.D_main.respawnparm := l_demobuffer.respawnparm i_main.D_main.fastparm := l_demobuffer.fastparm i_main.D_main.nomonsters := l_demobuffer.nomonsters consoleplayer := l_demobuffer.consoleplayer from i := 0 until i >= {DOOMDEF_H}.maxplayers loop Playeringame [i] := l_demobuffer.playeringame [i] i := i + 1 end if Playeringame [1] then netgame := True netdemo := True end precache := False g_initnew (skill, episode, map) precache := True usergame := False demoplayback := True end end end g_recorddemo (name: STRING_8) local i: INTEGER_32 maxsize: INTEGER_32 do usergame := False demoname := name + ".lmp" maxsize := 131072 i := i_main.m_argv.m_checkparm ("-maxdemo") if i.to_boolean and i < i_main.m_argv.myargv.count - 1 then maxsize := i_main.m_argv.myargv [i + 1].to_integer * 1024 end create demobuffer.make (maxsize) demorecording := True end g_playerfinishlevel (player: INTEGER_32) -- Can when a player completes a level. local p: PLAYER_T do p := Players [player] p.powers.fill_with (0) p.cards.fill_with (False) check attached p.mo as mo then mo.flags := mo.flags & {P_MOBJ}.mf_shadow.bit_not end p.extralight := 0 p.fixedcolormap := 0 p.damagecount := 0 p.bonuscount := 0 end cpars: ARRAY [INTEGER_32] pars: ARRAY [ARRAY [INTEGER_32]] statcopy: detachable WBSTARTSTRUCT_T g_docompleted local i: INTEGER_32 returned: BOOLEAN do gameaction := Ga_nothing from i := 0 until i >= Maxplayers loop if Playeringame [i] then g_playerfinishlevel (i) end i := i + 1 end if i_main.Am_map.automapactive then i_main.Am_map.am_stop end if i_main.Doomstat_h.gamemode /= {GAME_MODE_T}.commercial then if gamemap = 8 then gameaction := Ga_victory returned := True elseif gamemap = 9 then from i := 0 until i >= Maxplayers loop Players [i].didsecret := True i := i + 1 end end if not returned then wminfo.didsecret := Players [consoleplayer].didsecret wminfo.epsd := gameepisode - 1 wminfo.last := gamemap - 1 if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial then if secretexit then if gamemap = 15 then wminfo.next := 30 elseif gamemap = 31 then wminfo.next := 31 end else if gamemap = 31 or gamemap = 32 then wminfo.next := 15 else wminfo.next := gamemap end end else if secretexit then wminfo.next := 8 elseif gamemap = 9 then if gameepisode = 1 then wminfo.next := 3 elseif gameepisode = 2 then wminfo.next := 5 elseif gameepisode = 3 then wminfo.next := 6 elseif gameepisode = 4 then wminfo.next := 2 end else wminfo.next := gamemap end end wminfo.maxkills := totalkills wminfo.maxitems := totalitems wminfo.maxsecret := totalsecret wminfo.maxfrags := 0 if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial then wminfo.partime := 35 * cpars [gamemap - 1] else wminfo.partime := 35 * pars [gameepisode] [gamemap] end wminfo.pnum := consoleplayer from i := 0 until i >= Maxplayers loop wminfo.Plyr [i].in := Playeringame [i] wminfo.Plyr [i].skills := Players [i].killcount wminfo.Plyr [i].sitems := Players [i].itemcount wminfo.Plyr [i].ssecret := Players [i].secretcount wminfo.Plyr [i].stime := i_main.P_tick.leveltime; wminfo.Plyr [i].Frags.copy (Players [i].frags) i := i + 1 end gamestate := Gs_intermission viewactive := False i_main.Am_map.automapactive := False if attached statcopy as statcopy_attached then statcopy_attached.copy (wminfo) end i_main.Wi_stuff.wi_start (wminfo) end end end g_worlddone do gameaction := Ga_worlddone if secretexit then Players [consoleplayer].didsecret := True end if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial then if gamemap = 15 or gamemap = 31 and not secretexit then elseif gamemap = 6 or gamemap = 11 or gamemap = 20 or gamemap = 30 or gamemap = 15 or gamemap = 31 then i_main.F_finale.f_startfinale end end end g_doworlddone do gamestate := Gs_level gamemap := wminfo.next + 1 g_doloadlevel gameaction := Ga_nothing viewactive := True end feature Players: ARRAY [PLAYER_T] local i: INTEGER_32 once create Result.make_filled (create {PLAYER_T}.make, 0, {DOOMDEF_H}.maxplayers - 1) from i := 0 until i >= {DOOMDEF_H}.maxplayers loop Result [i] := create {PLAYER_T}.make i := i + 1 end end player_index (p: PLAYER_T): INTEGER_32 do Result := {UTILS [PLAYER_T]}.first_index (Players, p) ensure Players [Result] = p end Playeringame: ARRAY [BOOLEAN] once create Result.make_filled (False, 0, {DOOMDEF_H}.maxplayers - 1) end feature g_responder (ev: EVENT_T): BOOLEAN do {NOT_IMPLEMENTED}.not_implemented ("G_Responder", False) if gamestate = {DOOMDEF_H}.gs_level and ev.type = {EVENT_T}.ev_keydown and ev.data1 = {DOOMDEF_H}.key_f12 and (singledemo or not deathmatch) then from displayplayer := (displayplayer + 1) \\ Maxplayers until Playeringame [displayplayer] and displayplayer /= consoleplayer loop displayplayer := (displayplayer + 1) \\ Maxplayers end Result := True else if gameaction = Ga_nothing and not singledemo and (demoplayback or gamestate = Gs_demoscreen) then if ev.type = {EVENT_T}.ev_keydown or (ev.type = {EVENT_T}.ev_mouse and ev.data1 /= 0) or (ev.type = {EVENT_T}.ev_joystick and ev.data1 /= 0) then i_main.M_menu.m_startcontrolpanel Result := True else Result := False end else if gamestate = Gs_level and then i_main.Hu_stuff.hu_responder (ev) then Result := True elseif gamestate = Gs_level and then i_main.St_stuff.st_responder (ev) then Result := True elseif gamestate = Gs_level and then i_main.Am_map.am_responder (ev) then Result := True elseif gamestate = Gs_finale and then i_main.F_finale.f_responder (ev) then Result := True else if ev.type = {EVENT_T}.ev_keydown then if ev.data1 = Key_pause then sendpause := True else if ev.data1 < Numkeys then Gamekeydown [ev.data1] := True end end Result := True elseif ev.type = {EVENT_T}.ev_keyup then if ev.data1 < Numkeys then Gamekeydown [ev.data1] := False end Result := False elseif ev.type = {EVENT_T}.ev_mouse then setmousebuttons (ev.data1) mousex := ev.data2 * (i_main.M_menu.mousesensitivity + 5) // 10 mousey := ev.data3 * (i_main.M_menu.mousesensitivity + 5) // 10 Result := True end end end end end setmousebuttons (a_button_mask: INTEGER_32) local i: INTEGER_32 button_mask: NATURAL_32 button_on: BOOLEAN do button_mask := a_button_mask.as_natural_32 from i := 0 until i >= {I_INPUT}.max_mouse_buttons loop button_on := (button_mask & ({NATURAL_32} 1 |<< i)) /= 0 Mousebuttons [i] := button_on i := i + 1 end end feature -- G_PlayDemo defdemoname: detachable STRING_8 g_deferedplaydemo (name: STRING_8) do defdemoname := name gameaction := Ga_playdemo end feature g_deathmatchspawnplayer (playernum: INTEGER_32) -- Spawns a player at one of the random death match spots -- called at level load and each death do {NOT_IMPLEMENTED}.not_implemented ("G_DeathMatchSpawnPlayer", False) end feature g_playerreborn (player: INTEGER_32) -- Called after a player dies -- almost everything is cleared and initialized local p: PLAYER_T i: INTEGER_32 frags: ARRAY [INTEGER_32] killcount: INTEGER_32 itemcount: INTEGER_32 secretcount: INTEGER_32 do create frags.make_empty frags.copy (Players [player].frags) killcount := Players [player].killcount itemcount := Players [player].itemcount secretcount := Players [player].secretcount p := Players [player] p.reset p.frags.copy (frags) p.killcount := killcount p.secretcount := secretcount p.usedown := True p.attackdown := True p.playerstate := {PLAYER_T}.pst_live p.health := {P_LOCAL}.maxhealth p.readyweapon := Wp_pistol p.pendingweapon := Wp_pistol p.weaponowned [Wp_fist] := True p.weaponowned [Wp_pistol] := True p.ammo [Am_clip] := 50 from i := 0 until i >= Numammo loop p.maxammo [i] := {P_INTER}.maxammo [i] i := i + 1 end end invariant cpars.lower = 0 and cpars.count = 32 pars.lower = 1 and pars.count = 3 and across pars as p all p.item.lower = 1 and p.item.count = 9 end end -- class G_GAME
Generated by ISE EiffelStudio