#!/usr/bin/env perl
#---------------------------------------------------------------------
# file information
#---------------------------------------------------------------------
# prfreeboom.wrapper - Wrapper for "prfreeboom" main program
# License: Creative Commons CC BY-NC-SA 4.0 International
# Revision: See $REVISION in the code
# Note: The license indicated above applies to this file. It doesn't
# apply to PRBoom or FreeDoom, or to any files derived from those
# packages.
#---------------------------------------------------------------------
# license information
#---------------------------------------------------------------------
# This section may not be modified except as approved by the author or
# licensor, or to make non-content changes such as adjustments to par-
# agraph formatting or white space.
# This version of this software is distributed under the following
# license:
#
# Creative Commons CC BY-NC-SA 4.0 International
# You may use, modify, and redistribute this software without fees or
# royalties, but only under the terms and conditions set forth by the
# license. In particular, copies and derived works cannot be used for
# commercial purposes. Additionally, the license propagates to copies
# and derived works. Furthermore, you must provide attribution "in the
# manner specified by the author or licensor".
# This is not a complete explanation of the terms and conditions in-
# volved. For more information, see the official text of the license.
#---------------------------------------------------------------------
# explanation
#---------------------------------------------------------------------
# 1. Overview:
# This program (prfreeboom) is a GUI that launches a modified version
# of PRBoom using data files derived from FreeDoom.
# Note: PRBoom and FreeDoom are distributed under their own licenses.
# All associated modifications and/or data files are distributed under
# the same PRBoom and/or FreeDoom licenses. This program (prfreeboom)
# is a separate component that's distributed under its own license, as
# explained previously.
#---------------------------------------------------------------------
# 2. Features: The GUI allows the user to select a level and to set
# various options, such as:
#
# Science Fiction characters vs. original characters
# Alternate music vs. original music
# High resolution (1024x768 and up) vs. low resolution (640x480)
# etc.
# Additionally, the GUI allows the user to generate entirely new le-
# vels via Slige or Slump.
# The GUI also displays a brief list of command keys and some back-
# ground information.
#---------------------------------------------------------------------
# 3. Requirements:
# At the GUI level, this program requires Perl 5, Perl-Gtk2, LACSUB,
# and "glxinfo". These components are standard, except for LACSUB. You
# should be able to obtain LACSUB from the same place as this file.
# Note: LACSUB (like this file) is distributed under a Creative Com-
# mons license.
# For this program to be useful, the following additional items should
# be installed:
#
# a. A modified copy of PRBoom. You should be able to get the
# source code used from the same place as this file.
#
# b. A modified copy of FreeDoom. You should be able to get the
# data tree used from the same place as this file.
#
# c. "bsp", "deutex440", "slige", and "slump". These are standard
# Doom 1/Doom2 utilities, with some patches applied. "deutex-
# 440" is a special case: this must be "deutex" 4.4.0 exactly,
# with the associated "noshrink" patch applied. You should be
# able to get the complete source code for all of these utili-
# ties (plus all patches) from the same place as this file.
#
# d. "mus2pwad". This is a new Doom 1/Doom 2 utility. You should
# be able to get the complete source code used from the same
# place as this file. Note: "mus2pwad" is distributed under the
# same license as this file.
#---------------------------------------------------------------------
# standard module setup
#---------------------------------------------------------------------
require 5.16.1 ;
use strict ;
use Carp ;
use warnings ;
# Trap warnings
$SIG {__WARN__} = sub { die @_; };
#---------------------------------------------------------------------
# add CPAN module(s)
#---------------------------------------------------------------------
use Gtk2 '-init';
use Gtk2::SimpleList;
use Gtk2::Gdk::Keysyms;
use Gtk2::Pango;
use Pango;
#---------------------------------------------------------------------
# add LACSUB module(s)
#---------------------------------------------------------------------
use LACSUB::GUI
( @LACSUB::GUI::EXPORT_OK );
#---------------------------------------------------------------------
# basic constants
#---------------------------------------------------------------------
use constant ZERO => 0; # Zero
use constant ONE => 1; # One
use constant TWO => 2; # Two
use constant FALSE => 0; # Boolean FALSE
use constant TRUE => 1; # Boolean TRUE
#---------------------------------------------------------------------
# program parameters
#---------------------------------------------------------------------
# Presently, "prfreeboom" doesn't work well on some systems in OpenGL
# mode. This may be related to XOrg video-driver and/or Mesa issues.
# Until the problem can be resolved, $DISABLE_DRI should be set to
# TRUE; this disables the use of OpenGL. If the problem is resolved
# eventually, you can try setting $DISABLE_DRI to FALSE.
my $DISABLE_DRI = TRUE;
#---------------------------------------------------------------------
my $DIR_BASE = '__META_PREFIX__';
my $DIR_BIN = "$DIR_BASE/bin";
my $DIR_DATA = "$DIR_BASE/data";
my $DIR_LEVELS = "$DIR_DATA/levels";
my $FILE_FD1 = "$DIR_DATA/freedoom1.wad";
my $FILE_FD2 = "$DIR_DATA/freedoom2.wad";
my $FILE_FDALT = "$DIR_DATA/freedm.wad";
my $FILE_COMBINED = "$DIR_DATA/combined.wad";
my $ALERT_ICON_PATH = "$DIR_DATA/alert.png";
my $MAIN_WIDTH = 900; # Main-window width (in pixels)
my $MAIN_HEIGHT = 610; # Main-window height (in pixels)
my $MAX_DOOM2_LEVNUM = 32; # Max. Doom 2 level number (32)
my $MAX_SLUMP_LEVELS = 100;
# Revision (or release) string
my $REVISION = '241113';
# Name of main "prfreeboom" configur-
# ation file (excluding path)
my $CFG_NAME_PRFREEBOOM = 'prfreeboom.cfg';
# Name of main "prboom-plus" configur-
# ation file (excluding path)
my $CFG_NAME_PRBOOM_PLUS = 'prboom-plus.cfg';
# Name of "slump" history file (ex-
# cluding path component)
my $SLUMP_HISTORY = 'slump.lst';
#---------------------------------------------------------------------
# @ProgNames specifies single-word names for one or more programs that
# are associated (directly or indirectly) with this package. At least
# one name should be specified. Note: List order and/or alphabetic
# case don't matter.
# $ProgNames contains the strings listed by @ProgNames, separated by
# vertical bars.
# @ProgNames isn't used after $ProgNames is constructed. $ProgNames is
# used to post-process message text.
my @ProgNames = qw
(
bsp deutex deutex440 doom freedoom
prboom prfreeboom slige slump
);
my $ProgNames = join '|', @ProgNames;
undef @ProgNames;
#---------------------------------------------------------------------
# $DEFAULT_PATTERN should be a Perl pattern string enclosed in paren-
# theses. "prfreeboom" checks WAD-file names against the specified
# pattern. Note: The check is done using base filenames. For the pur-
# poses of this check, pathname components and ".wad" filename exten-
# sions are ignored.
# If one WAD file's name matches the specified pattern (ignoring al-
# phabetic case), "prfreeboom" uses the WAD file as a default level.
# If there's a match for more than one file, an arbitrary selection is
# made.
my $DEFAULT_PATTERN = '(no-default)';
#---------------------------------------------------------------------
# $CFG_DEFAULT_PRFREEBOOM specifies the default contents of the main
# "prfreeboom" configuration file.
# Note: Normally, $CFG_DEFAULT_PRFREEBOOM shouldn't specify a default
# setting for "video_highres". The default setting for this flag is
# determined at runtime.
# "END" must be double-quoted here
my $CFG_DEFAULT_PRFREEBOOM = << "END";
# $CFG_NAME_PRFREEBOOM - Main "prfreeboom" configuration file
[prfreeboom]
alternate_music = yes
characters_sf = yes
save_slump = no
spider_robots = no
END
#---------------------------------------------------------------------
# $CFG_DEFAULT_PRBOOM_PLUS specifies the default contents of the main
# "prboom-plus" configuration file.
# 'END' should be single-quoted here
my $CFG_DEFAULT_PRBOOM_PLUS = << 'END';
# Video settings
videomode "8bit"
screen_width 640
screen_height 480
use_fullscreen 1
use_doublebuffer 1
translucency 1
tran_filter_pct 66
screenblocks 10
usegamma 3
uncapped_framerate 1
filter_wall 1
filter_floor 1
filter_sprite 1
filter_z 1
filter_patch 1
filter_threshold 49152
sprite_edges 0
patch_edges 0
# Key bindings
key_right 0xae
key_left 0xac
key_up 0xad
key_down 0xaf
key_mlook 0x5c
key_novert 0x0
key_menu_right 0xae
key_menu_left 0xac
key_menu_up 0xad
key_menu_down 0xaf
key_menu_backspace 0x7f
key_menu_escape 0x1b
key_menu_enter 0xd
key_menu_clear 0xc8
key_setup 0x0
key_strafeleft 0x61
key_straferight 0x64
key_flyup 0x60
key_flydown 0x2c
key_fire 0x9d
key_use 0xb6
key_strafe 0xb8
key_speed 0x2e
key_savegame 0xbc
key_loadgame 0xbd
key_soundvolume 0xbe
key_hud 0xbf
key_quicksave 0xc0
key_endgame 0xc1
key_messages 0xc2
key_quickload 0xc3
key_quit 0xc4
key_gamma 0xd7
key_spy 0xd8
key_pause 0xff
key_autorun 0xba
key_chat 0x74
key_backspace 0x7f
key_enter 0xd
key_map 0x9
key_map_right 0xae
key_map_left 0xac
key_map_up 0xad
key_map_down 0xaf
key_map_zoomin 0x3d
key_map_zoomout 0x2d
key_map_gobig 0x30
key_map_follow 0x66
key_map_mark 0x6d
key_map_clear 0x63
key_map_grid 0x67
key_map_rotate 0x72
key_map_overlay 0x6f
key_map_textured 0x0
key_reverse 0x2f
key_zoomin 0x3d
key_zoomout 0x2d
key_chatplayer1 0x67
key_chatplayer2 0x69
key_chatplayer3 0x62
key_chatplayer4 0x72
key_weapontoggle 0x30
key_weapon1 0x31
key_weapon2 0x32
key_weapon3 0x33
key_weapon4 0x34
key_weapon5 0x35
key_weapon6 0x36
key_weapon7 0x37
key_weapon8 0x38
key_weapon9 0x39
key_nextweapon 0xeb
key_prevweapon 0xec
key_screenshot 0x2a
END
#---------------------------------------------------------------------
# $SLUMP_HEADER specifies "comment" text to be placed at the start of
# a Slump history file. Note: "Comment" lines should begin with a
# "#".
my $SLUMP_HEADER = << "END"; # "END" must be single-quoted here
# $SLUMP_HISTORY - prfreeboom/slump level-generator keys
# You can use this list to reproduce "slump" levels that have been
# used in the past.
END
#---------------------------------------------------------------------
# @SLUMP_DEFAULT_SEEDS should be a list of one or more strings for-
# mated as follows:
#
# integer dash three-digit-integer
# The first integer is interpreted as a standard Slump level-generator
# seed.
# The second integer may start with digit "1" or "2". "1" selects Doom
# 1 and "2" selects Doom 2.
# If Doom 1 is selected, the second digit of the second integer speci-
# fies a Doom 1 Episode number and the third (and final) digit speci-
# fies a Doom 1 Mission number.
# If Doom 2 is selected, the last two digits of the second integer
# specify a Doom 2 Map number (01 to 32).
# Together, the two integers (plus the dash separator) specify a com-
# plete prfreeboom/Slump level-generator key.
# The values used may be arbitrary, or they may be the level-generator
# seeds for specific prfreeboom/Slump levels that you've used in the
# past.
# Note: "prfreeboom's" Slump interface screen doesn't support empty
# Slump history files; this would complicate the code unnecessarily.
# Therefore, the @SLUMP_DEFAULT_SEEDS list must contain at least one
# entry.
my @SLUMP_DEFAULT_SEEDS = qw
(
1176585748-201 1176600739-201 1176607388-201 1176672985-201
);
#---------------------------------------------------------------------
# "prfreeboom" configuration-file variables
#---------------------------------------------------------------------
# This section defines variables related to the main "prfreeboom" con-
# figuration file (as opposed to configuration files related to
# "prboom", "slump", etc.).
my $CFG_PATH_PRFREEBOOM; # Absolute pathname for file
my $CFG_DATA; # Contents of file
# Note: The following flag settings are defaults. They may be over-
# ridden by the user's "prfreeboom" configuration file and/or GUI-
# level actions.
#---------------------------------------------------------------------
# Associated flags.
my $CFG_AltMusic = TRUE ;
my $CFG_BeauDoom = TRUE ;
my $CFG_Leggo = FALSE ;
my $CFG_Save_Slump = TRUE ;
my $CFG_SciFi = TRUE ;
my $CFG_Spiders = FALSE ;
my $CFG_HighRes; # This flag is handled at runtime
#---------------------------------------------------------------------
# misc. global variables
#---------------------------------------------------------------------
my $CFG_PATH_PRBOOM_PLUS; # Absolute pathname for "prboom-plus.
# cfg"
my $FlagDirectRendering; # Flag: Direct rendering is available
my $FlagHighResolution; # Flag: High-resolution mode
my $MainWindow; # GTK2 main window
my $SLUMPFILE; # "slump" history file (pathname)
my %WadMap = (); # Maps WAD descriptions to pathnames
# The following variables are Perl-Gtk2 objects:
my $SimpleList; # SimpleList: List of level names
# Checkboxes:
#
my $CB_AltMusic ; # Alternate Music
my $CB_HighRes ; # High resolution
my $CB_Save_Slump ; # Save Slump levels
my $CB_Spiders ; # Spider robots
my $CB_BeauDoom ; # BeauDoom mode
my $CB_Leggo ; # Leggo mode
my $CB_SciFi ; # Sci-Fi mode
#---------------------------------------------------------------------
# support routines
#---------------------------------------------------------------------
# "by_number" is a "sort"-compatible routine that's used as follows:
#
# @list = sort by_number @list;
# @list should contain a list of strings in the following format:
#
# integer or integer-string
# The code shown above sorts the list into ascending numeric order
# based on the leading integer.
#---------------------------------------------------------------------
sub by_number
{
my ($s1, $s2) = ($a, $b);
$s1 =~ s@-.*@@;
$s2 =~ s@-.*@@;
$s1 <=> $s2;
}
#---------------------------------------------------------------------
# "reverse_by_number" is a "sort"-compatible routine that's used as
# follows:
#
# @list = sort reverse_by_number @list;
# @list should contain a list of strings in the following format:
#
# integer or integer-string
# The code shown above sorts the list into descending numeric order
# based on the leading integer.
#---------------------------------------------------------------------
sub reverse_by_number
{
my ($s1, $s2) = ($a, $b);
$s1 =~ s@-.*@@;
$s2 =~ s@-.*@@;
$s2 <=> $s1;
}
#---------------------------------------------------------------------
# Future change: Document this routine.
sub PanicDialog
{
my ($msg, $details) = @_;
$msg = "" unless defined $msg;
$msg =~ s@^\s+@@s;
$msg =~ s@\s+\z@@s;
$msg =~ s@\s+@ @gs;
$msg = '???' unless length $msg;
$msg = "#$msg" if $msg =~ m@^\d+\z@;
$msg = ": $msg" unless $msg =~ m@^#@;
$msg = " $msg" unless $msg =~ m@^:@;
$details = "" unless defined $details;
$details =~ s@^\s+@@s;
$details =~ s@\s+\z@@s;
$details =~ s@\s+@ @gs;
if (!length ($details))
{
$details = << 'END'; # 'END' must be single-quoted here
This might be an I/O problem, a privileges problem, or a bug in the
program.
END
}
my $text = << "END"; # "END" must be double-quoted here
Internal error$msg
$details
END
my %args =
(
-dimensions => '550x225' ,
-text => $text ,
-title => 'Internal error' ,
-action_quit => "quit" ,
-top_space => 2
);
$args {-icon_path} = $ALERT_ICON_PATH if
defined ($ALERT_ICON_PATH) &&
(-f $ALERT_ICON_PATH) && (-r $ALERT_ICON_PATH) &&
(-B $ALERT_ICON_PATH);
&SimpleDialogBox (%args);
undef;
}
#---------------------------------------------------------------------
# "CheckDirectRendering" checks the status of direct rendering and
# sets the associated global flag appropriately. Note: If the flag in
# question has already been set, this code simply returns.
sub CheckDirectRendering
{
return if defined $FlagDirectRendering;
my $str; # Scratch
$str = `glxinfo 2>&1`;
$str = "" unless defined $str;
# Is direct rendering supported?
if ($str =~ m@direct rendering: Yes@)
{ # Yes
$FlagDirectRendering = TRUE;
}
else
{ # No
$FlagDirectRendering = FALSE;
}
undef;
}
#---------------------------------------------------------------------
# Future change: Document this routine.
sub LocateSlumpHistory
{
my $str; # Scratch
my $HOME = $ENV {HOME};
&PanicDialog ("#$REVISION-0001") unless defined ($HOME);
$str = "$HOME/.prboom-plus";
system "mkdir -p $str" unless -d $str;
$SLUMPFILE = "$str/$SLUMP_HISTORY" if -d $str;
if ((!-f $SLUMPFILE) || (-z $SLUMPFILE))
{
open (OFD, ">>$SLUMPFILE") ||
&PanicDialog ("#$REVISION-0002");
$SLUMP_HEADER =~ s@\s*\z@\n\n@;
print OFD $SLUMP_HEADER;
@SLUMP_DEFAULT_SEEDS = sort by_number @SLUMP_DEFAULT_SEEDS;
for (@SLUMP_DEFAULT_SEEDS) { print OFD "$_\n"; }
close (OFD) || &PanicDialog ("#$REVISION-0003");
}
undef;
}
#---------------------------------------------------------------------
# Future change: Document this routine.
sub Load_CFG_PRFREEBOOM
{
my $data; # Data buffer
my $str; # Scratch
#---------------------------------------------------------------------
# Initial setup.
my $HOME = $ENV {HOME};
&PanicDialog ("#$REVISION-0004") unless defined ($HOME);
$str = "$HOME/.prboom-plus";
system "mkdir -p $str" unless -d $str;
&PanicDialog ("#$REVISION-0005") unless -d $str;
# Absolute pathname for config. file
$CFG_PATH_PRFREEBOOM = "$str/$CFG_NAME_PRFREEBOOM";
&CheckDirectRendering(); # Check status of direct rendering
# Code may override this setting at a
# later point
$CFG_HighRes = $FlagDirectRendering;
#---------------------------------------------------------------------
# Create configuration file (if necessary).
if ((!-f $CFG_PATH_PRFREEBOOM) || (-z $CFG_PATH_PRFREEBOOM))
{
open (OFD, ">$CFG_PATH_PRFREEBOOM") ||
&PanicDialog ("#$REVISION-0006");
$CFG_DEFAULT_PRFREEBOOM =~ s@\s*\z@\n@;
print OFD $CFG_DEFAULT_PRFREEBOOM;
close (OFD) || &PanicDialog ("#$REVISION-0007");
}
#---------------------------------------------------------------------
# Read (entire) configuration file.
open (IFD, "<$CFG_PATH_PRFREEBOOM") ||
&PanicDialog ("#$REVISION-0008");
undef $/;
binmode IFD;
$data = ;
$data = "" unless defined $data;
close IFD;
#---------------------------------------------------------------------
# Save a global copy.
$CFG_DATA = $data;
#---------------------------------------------------------------------
# Apply settings.
$data =~ y/\011\040/ /s;
$data =~ s@ *#[^\012]*@@g;
$data =~ s@ *= *(0|no?|off|zero|false)\b@=no@gi;
$data =~ s@ *= *(1|y|yes|one?|true)\b@=yes@gi;
if ($data =~ m@\nalternate_music=(\w+)@)
{
$CFG_AltMusic = ($1 eq 'yes') ? TRUE : FALSE;
}
if ($data =~ m@\nbeautiful=(\w+)@)
{
$CFG_BeauDoom = ($1 eq 'yes') ? TRUE : FALSE;
}
if ($data =~ m@\ncharacters_sf=(\w+)@)
{
$CFG_SciFi = ($1 eq 'yes') ? TRUE : FALSE;
}
if ($data =~ m@\nleggo=(\w+)@)
{
$CFG_Leggo = ($1 eq 'yes') ? TRUE : FALSE;
}
if ($data =~ m@\nsave_slump=(\w+)@)
{
$CFG_Save_Slump = ($1 eq 'yes') ? TRUE : FALSE;
}
if ($data =~ m@\nspider_robots=(\w+)@)
{
$CFG_Spiders = ($1 eq 'yes') ? TRUE : FALSE;
}
if ($data =~ m@\nvideo_highres=(\w+)@)
{
$CFG_HighRes = ($1 eq 'yes') ? TRUE : FALSE;
}
undef;
}
#---------------------------------------------------------------------
# Future change: Document this routine.
sub Update_CFG_PRFREEBOOM
{
my $data; # Data buffer
my $str; # Scratch
#---------------------------------------------------------------------
# Initial setup.
&PanicDialog ("#$REVISION-0009")
unless defined ($CFG_PATH_PRFREEBOOM) && defined ($CFG_DATA);
#---------------------------------------------------------------------
# Adjust in-memory contents based on GUI settings.
my $V_AltMusic = $CB_AltMusic ->get_active
? 'yes' : 'no';
my $V_BeauDoom = $CB_BeauDoom ->get_active
? 'yes' : 'no';
my $V_HighRes = $CB_HighRes ->get_active
? 'yes' : 'no';
my $V_Leggo = $CB_Leggo ->get_active
? 'yes' : 'no';
my $V_Save_Slump = $CB_Save_Slump ->get_active
? 'yes' : 'no';
my $V_SciFi = $CB_SciFi ->get_active
? 'yes' : 'no';
my $V_Spiders = $CB_Spiders ->get_active
? 'yes' : 'no';
my $BlockPat = '\[prfreeboom\][^\012]*\n';
my $WSZ = '[\011\040]*';
my $EQWSZ = "$WSZ=$WSZ";
my $OrigData = $CFG_DATA;
if ($CFG_DATA !~
s@(\nalternate_music$EQWSZ)\w+@$1$V_AltMusic@i)
{
$str = "alternate_music=$V_AltMusic\n";
$CFG_DATA =~ s@\nalternate_music$EQWSZ[^\012]*@@gi;
$CFG_DATA =~ s@($BlockPat)@$1$str@i;
}
if ($CFG_DATA !~
s@(\ncharacters_sf$EQWSZ)\w+@$1$V_SciFi@i)
{
$str = "characters_sf=$V_SciFi\n";
$CFG_DATA =~ s@\ncharacters_sf$EQWSZ[^\012]*@@gi;
$CFG_DATA =~ s@($BlockPat)@$1$str@i;
}
if ($CFG_DATA !~
s@(\nbeautiful$EQWSZ)\w+@$1$V_BeauDoom@i)
{
$str = "beautiful=$V_BeauDoom\n";
$CFG_DATA =~ s@\nbeautiful$EQWSZ[^\012]*@@gi;
$CFG_DATA =~ s@($BlockPat)@$1$str@i;
}
if ($CFG_DATA !~
s@(\nleggo$EQWSZ)\w+@$1$V_Leggo@i)
{
$str = "leggo=$V_Leggo\n";
$CFG_DATA =~ s@\nleggo$EQWSZ[^\012]*@@gi;
$CFG_DATA =~ s@($BlockPat)@$1$str@i;
}
if ($CFG_DATA !~
s@(\nsave_slump$EQWSZ)\w+@$1$V_Save_Slump@i)
{
$str = "save_slump=$V_Save_Slump\n";
$CFG_DATA =~ s@\nsave_slump$EQWSZ[^\012]*@@gi;
$CFG_DATA =~ s@($BlockPat)@$1$str@i;
}
if ($CFG_DATA !~
s@(\nspider_robots$EQWSZ)\w+@$1$V_Spiders@i)
{
$str = "spider_robots=$V_Spiders\n";
$CFG_DATA =~ s@\nspider_robots$EQWSZ[^\012]*@@gi;
$CFG_DATA =~ s@($BlockPat)@$1$str@i;
}
if ($CFG_DATA !~
s@(\nvideo_highres$EQWSZ)\w+@$1$V_HighRes@i)
{
$str = "video_highres=$V_HighRes\n";
$CFG_DATA =~ s@\nvideo_highres$EQWSZ[^\012]*@@gi;
$CFG_DATA =~ s@($BlockPat)@$1$str@i;
}
$CFG_DATA =~ s@\s*\z@\n@;
#---------------------------------------------------------------------
# Update disk copy.
if ($CFG_DATA ne $OrigData)
{
open (OFD, ">$CFG_PATH_PRFREEBOOM") ||
&PanicDialog ("#$REVISION-0010");
binmode OFD;
print OFD $CFG_DATA;
close (OFD) || &PanicDialog ("#$REVISION-0011");
}
undef;
}
#---------------------------------------------------------------------
# Future change: Document this routine.
sub Update_CFG_PRBOOM_PLUS
{
my $data; # Data buffer
my $orig_data; # Copy of original data
my $str; # Scratch
#---------------------------------------------------------------------
# Initial setup.
my $HOME = $ENV {HOME};
&PanicDialog ("#$REVISION-0012") unless defined ($HOME);
$str = "$HOME/.prboom-plus";
system "mkdir -p $str" unless -d $str;
&PanicDialog ("#$REVISION-0013") unless -d $str;
&CheckDirectRendering(); # Check status of direct rendering
# Absolute pathname for config. file
$CFG_PATH_PRBOOM_PLUS = "$str/$CFG_NAME_PRBOOM_PLUS";
#---------------------------------------------------------------------
# Create configuration file (if necessary).
if ((!-f $CFG_PATH_PRBOOM_PLUS) || (-z $CFG_PATH_PRBOOM_PLUS))
{
open (OFD, ">$CFG_PATH_PRBOOM_PLUS") ||
&PanicDialog ("#$REVISION-0014");
$CFG_DEFAULT_PRBOOM_PLUS =~ s@\s*\z@\n@;
print OFD $CFG_DEFAULT_PRBOOM_PLUS;
close (OFD) || &PanicDialog ("#$REVISION-0015");
}
#---------------------------------------------------------------------
# Read (entire) configuration file.
open (IFD, "<$CFG_PATH_PRBOOM_PLUS") ||
&PanicDialog ("#$REVISION-0016");
undef $/;
binmode IFD;
$data = ;
$data = "" unless defined $data;
$orig_data = $data;
close IFD;
#---------------------------------------------------------------------
# Make necessary adjustment(s).
# Note: We don't need to adjust screen width or height at the config-
# uration-file level. ExecTarget sets these two parameters appropri-
# ately at the CLI level.
if ($DISABLE_DRI)
{
$str = $FlagHighResolution ? "16bit" : "8bit";
}
else
{
$str = ($FlagHighResolution && $FlagDirectRendering)
? "OpenGL" : "8bit";
}
$data =~ s@(^|\n)(\s*videomode[\011\040]+)("[^"]*")@$1$2"$str"@i;
#---------------------------------------------------------------------
# Write data back to configuration file (if necessary).
if ($data ne $orig_data) # Did we change anything?
{ # Yes
open (OFD, ">$CFG_PATH_PRBOOM_PLUS") ||
&PanicDialog ("#$REVISION-0017");
print OFD $data;
close (OFD) || &PanicDialog ("#$REVISION-0018");
}
undef;
}
#---------------------------------------------------------------------
# "ExecTarget" runs the target program or passes control to a new
# screen. The details are as follows:
# "ExecTarget" assumes that $SimpleList is the current selection list
# and that the user has selected one of the entries in $SimpleList.
# This version of "ExecTarget" supports two entry types:
#
# a. Level-generator strings of the following form:
#
# Slump \d+-\d+
#
# Note: For an explanation of the "\d+-\d+" format shown here,
# see the comments preceding the definition of @SLUMP_DEFAULT_
# SEEDS.
#
# b. Any string that's a valid %WadMap key.
# In case (a), "ExecTarget" creates the specified prfreeboom/Slump le-
# vel (including alternate music) and runs it. To create the level
# (and alternate music), "bsp", "deutex440", "slump", and a package-
# specific utility named "mus2pwad" are used. To run the level, modi-
# fied copies of "prboom" and "freedoom" are used.
# In case (b), "ExecTarget" looks up the specified string using "%Wad-
# Map". Five result types are supported:
#
# b1. String "__META_FREEDM__". This result tells "ExecTarget" to
# play FreeDoom.
#
# b2. String "__META_SLIGE__". This result tells "ExecTarget" to
# create and run a new Slige level.
#
# b3. String "__META_SLUMP__". This result tells "ExecTarget" to
# create and run a new Slump level.
#
# b4. A WAD-file pathname. This result tells "ExecTarget" to run
# the level stored in the specified file.
#
# b5. String "__META_OLDSLUMP__". This result tells "ExecTarget"
# to start a Slump saved-levels selection screen. Note: The
# selection screen in question may call "ExecTarget", in turn,
# to trigger case (a) (which was discussed previously).
# "ExecTarget" supports alternate music for cases (b2) through (b4).
# Additionally, for case (b3), it saves the level-generator key used
# for future use (unless the user has disabled this feature).
# "ExecTarget" uses "system" (as opposed to "exec") to start "prboom".
# This allows "ExecTarget" to clean up temporary files after the lat-
# ter program exits.
# Note: You should be able to obtain source code for the following
# utilities and/or datasets from the same place as this file: bsp,
# deutex440, freedoom, midi2pwad, prboom, slige, and slump.
#---------------------------------------------------------------------
sub ExecTarget
{
my $n; # Scratch (integer)
my $str; # Scratch (string )
my $FlagDoom2; # Flag: Doom 2 (as opposed to Doom 1)
my $MapSelector; # Slump map selector (either -E#M# or
# -map##, where each "#" is a single
# digit)
my $wad; # WAD-file pathname (or a meta-symbol
# that selects a WAD-file mode)
my ($width, $height); # Display width/height used
my @tmpfiles = (); # Temporary-file pathnames
#---------------------------------------------------------------------
# "prfreeboom" uses two kinds of level-generator keys:
#
# a. Standard Slump seeds of the form \d+
# b. High-level "prfreeboom/Slump" keys of the form \d+-\d+
# Note: For an explanation of the "prfreeboom/Slump" level-generator
# key format, see the comments preceding the definition of @SLUMP_
# DEFAULT_SEEDS.
# If $OldLevel is defined, it specifies a standard Slump seed (as op-
# posed to a "prfreeboom/Slump" level-generator key).
my $OldLevel;
#---------------------------------------------------------------------
# Initial setup.
$FlagHighResolution = $CB_HighRes->get_active ? TRUE : FALSE;
&Update_CFG_PRFREEBOOM(); # Update "prfreeboom" config. file
&Update_CFG_PRBOOM_PLUS(); # Update "prboom-plus" config. file
#---------------------------------------------------------------------
# Identify selected level (or mode).
my ($model, $iter) = $SimpleList->get_selection->get_selected;
my $selected = $model->get ($iter, ZERO);
if ($selected =~ m@Play FreeDoom@)
{
# The rest of this case is handled by
# the __META_FREEDM__ support code
$wad = '__META_FREEDM__';
}
elsif ($selected =~ m@^Slump (\d+)-(\d)(\d)(\d)\b@)
{ # See notes preceding this routine
$OldLevel = $1; # This part is a standard Slump seed
if ($2 eq '1')
{ # Doom 1 mode is selected
$FlagDoom2 = FALSE;
$MapSelector = "-E$3M$4";
# Consistency check
&PanicDialog ("#$REVISION-0019")
if ($3 < 1) || ($3 > 3) || ($4 < 1);
}
elsif ($2 eq '2')
{ # Doom 2 mode is selected
$FlagDoom2 = TRUE;
$MapSelector = "-map$3$4";
}
else
{ # Internal error
&PanicDialog ("#$REVISION-0020");
}
# The rest of this case is handled by
# the __META_SLUMP__ support code
$wad = '__META_SLUMP__';
}
elsif ($selected =~ m@^Slump@)
{ # Internal error
&PanicDialog ("#$REVISION-0021");
}
else
{ # See notes preceding this routine
$wad = $WadMap {$selected};
}
# Consistency check
&PanicDialog ("#$REVISION-0022") unless defined $wad;
#---------------------------------------------------------------------
# Handle a special case.
# For more information on the PRFREESKULL variable used below, see the
# code in "slump.spcpat". You should be able to obtain the latter
# file from the same place as this file.
if ($CB_SciFi->get_active &&
!$CB_Spiders->get_active)
{ # S.F. characters are enabled and Spi-
# der Robots are disabled
$ENV {PRFREESKULL} = 'no';
}
else
{
delete $ENV {PRFREESKULL};
}
#---------------------------------------------------------------------
# Handle the various WAD-file modes.
my $GeneratedLevel = FALSE; # Flag: Generated a level
if ($wad eq '__META_SLIGE__')
{ # See notes preceding this routine
my $xtmpbase = "/var/tmp/prfreeboom-$>-$$-slige";
$wad = "$xtmpbase.wad";
push (@tmpfiles, $wad);
# Build appropriate command sequence
$str = << "END"; # "END" must be double-quoted here
slige $xtmpbase.dat -doom2
bsp $xtmpbase.dat $wad
rm $xtmpbase.dat
END
print $str; # Print the commands to be used
system $str; # Run them
$GeneratedLevel = TRUE; # Assert that we generated a level
}
elsif ($wad eq '__META_SLUMP__')
{ # See notes preceding this routine
my $seed = defined ($OldLevel) ? $OldLevel : time;
my $xtmpbase = "/var/tmp/prfreeboom-$>-$$-slump";
$wad = "$xtmpbase.wad";
push (@tmpfiles, $wad);
&PanicDialog ("#$REVISION-0023") unless defined $SLUMPFILE;
&PanicDialog ("#$REVISION-0024") unless -f $SLUMPFILE;
&PanicDialog ("#$REVISION-0025") if -z $SLUMPFILE;
if (!defined $FlagDoom2)
{ # Select Doom 1 or Doom 2 mode
# This code picks Doom 2 about 80% of
# the time
$FlagDoom2 = TRUE;
$FlagDoom2 = FALSE if rand (100) < 20;
# Consistency check
&PanicDialog ("#$REVISION-0026")
if defined ($MapSelector);
}
else
{ # Doom 1 vs. Doom 2 is already decided
# Consistency check
&PanicDialog ("#$REVISION-0027")
unless defined ($MapSelector);
}
# Do we have a Slump map selector?
if (!defined $MapSelector)
{ # No - Create one
if ($FlagDoom2)
{ # Doom 2 mode
$n = ONE + int (rand ($MAX_DOOM2_LEVNUM));
$n = sprintf ('%02d', $n);
$MapSelector = "-map$n";
}
else
{ # Doom 1 mode
my ($n1, $n2);
$n1 = ONE + int (rand (3));
$n2 = ONE + int (rand (9));
$MapSelector = "-E${n1}M${n2}";
}
}
if (!defined ($OldLevel) && $CB_Save_Slump->get_active &&
open (OFD, ">>$SLUMPFILE"))
{ # Save prfreeboom/Slump level-genera-
# tor key for future use
my ($v1, $v2);
$v1 = $FlagDoom2 ? TWO : ONE;
$v2 = "$1$2" if $MapSelector =~ m@(\d)[a-z]?(\d)\z@i;
&PanicDialog ("#$REVISION-0028") unless defined ($v1);
&PanicDialog ("#$REVISION-0029") unless defined ($v2);
print OFD "$seed-$v1$v2\n";
}
# Build appropriate command sequence
$str = $FlagDoom2 ? " -doom2" : "";
$str = ""; # Doom2 mode no longer works here
$str = << "END"; # "END" must be double-quoted here
slump $xtmpbase.dat$str -levels 1 -seed $seed $MapSelector
bsp $xtmpbase.dat $wad
rm $xtmpbase.dat
END
print $str; # Print the commands to be used
system $str; # Run them
$GeneratedLevel = TRUE; # Assert that we generated a level
}
elsif ($wad eq '__META_OLDSLUMP__')
{ # See notes preceding this routine
&ReplayOldSlump();
exit (ZERO);
}
#---------------------------------------------------------------------
# Get initial display dimensions (if possible).
my $X11DIM;
$str = `getx11dim 2>&1`;
$str = "" unless defined $str;
$str =~ s@\s+\z@@s;
$X11DIM = $str if $str =~ m@^\d+x\d+\z@;
#---------------------------------------------------------------------
# Set up "prboom" command-line argument list.
if (!-f $FILE_COMBINED) # Do a basic configuration check
{ # Error - Explain things to the user
$str = << 'END';
prfreeboom requires modified copies of PRBoom, FreeDoom, and Slump.
You should be able to get source code from the same place as this
program.
END
$str =~ s@\b($ProgNames)('s|[\.,;]|\b)@@gi;
&PanicDialog ('Invalid setup', $str);
}
my @ARGS = # Start argument list
(
'-iwad', $FILE_COMBINED, '-file', $wad
);
$str = $wad;
die unless $str =~ s@\.wad\z@.deh@;
push (@ARGS, $str) if -f $str;
#ifdef NOTDEF
# @ARGS = ('-iwad', $FILE_FDALT) if $wad eq '__META_FREEDM__';
#endif
if (TRUE)
{
my @FileMUS = ();
my $FileMUS;
$str = $wad;
$str =~ s@\.wad\z@.mus@i;
$FileMUS = $str;
if ($CB_AltMusic->get_active && (!-f $str) &&
opendir (DIR, $DIR_LEVELS))
{
while (defined ($_ = readdir (DIR)))
{
next unless m@^_slump\S*\.mus\z@i;
$str = "$DIR_LEVELS/$_";
next unless -f $str;
push (@FileMUS, $str);
}
closedir DIR;
if (scalar @FileMUS)
{
$n = rand ($#FileMUS + ONE);
$FileMUS = $FileMUS [$n];
}
}
if (-f $FileMUS) # Is a ".mus" file selected?
{ # Yes - Translate it to PWAD format
my $tmpwad = "/var/tmp/prfreeboom-$>-$$-delete.wad";
unlink $tmpwad;
system << "END";
mus2pwad --music=$FileMUS --level=$wad --output=$tmpwad
END
if (-f $tmpwad)
{
print "Using alternate music file\n";
push (@ARGS , $tmpwad);
push (@tmpfiles , $tmpwad);
}
}
}
if ($CB_BeauDoom ->get_active && ($wad !~ m@(^|)tc_@i))
{ # BeauDoom mode
push (@ARGS, "$DIR_DATA/beautiful.wad" );
}
if ($CB_Leggo ->get_active && ($wad !~ m@(^|/)tc_@i))
{ # Leggo mode
push (@ARGS, "$DIR_DATA/leggo.wad");
}
if ($CB_SciFi ->get_active && ($wad !~ m@(^|)tc_@i))
{ # Science Fiction mode
push (@ARGS, "$DIR_DATA/monsters.wad" );
push (@ARGS, "$DIR_DATA/monsters.deh" );
}
if ($FlagHighResolution)
{ # Use high resolution if possible
my ($cw, $ch) = $X11DIM =~ m@^(\d+)x(\d+)@;
&PanicDialog ("#$REVISION-0030") unless defined $ch;
($width, $height) = ( 640, 480 );
($width, $height) = ( 1024, 768 )
if ($cw >= 1024) && ($ch >= 768);
($width, $height) = ( 1280, 900 )
if ($cw >= 1280) && ($ch >= 900);
($width, $height) = ( 1280, 1024 )
if ($cw >= 1280) && ($ch >= 1024);
$FlagHighResolution = FALSE if $width < 1024;
}
else
{ # Use low resolution
($width, $height) = ( 640, 480 );
}
# Finish argument list
push (@ARGS,
('-warp', 'x', '-width', $width, '-height', $height));
#---------------------------------------------------------------------
# Shut down menu level.
undef $SimpleList;
if (defined $MainWindow)
{
Gtk2->main_quit;
$MainWindow->destroy;
undef $MainWindow;
}
#---------------------------------------------------------------------
# Run the target program.
$SIG {CHLD} = "IGNORE";
system "$DIR_BASE/bin/prboom", @ARGS;
#---------------------------------------------------------------------
# Fix resulting display problems (if necessary).
if (defined ($X11DIM))
{
$str = `getx11dim 2>&1`;
$str = "" unless defined $str;
$str =~ s@\s+\z@@s;
system "/laclin/lacutil/setx11dim --fast $X11DIM"
unless $str eq $X11DIM;
#ifdef NOTDEF
# system "xclockmove";
#endif
}
#---------------------------------------------------------------------
# Wrap it up.
unlink @tmpfiles;
undef;
}
#---------------------------------------------------------------------
# special-key handler
#---------------------------------------------------------------------
sub SpecialKeyHandler
{
my $widget = shift;
my $event = shift;
my $keypress = $event->keyval;
if ($keypress == $Gtk2::Gdk::Keysyms {Escape})
{
Gtk2->main_quit;
$MainWindow->destroy;
exit (ONE);
}
if ($keypress == $Gtk2::Gdk::Keysyms {KP_Enter} ||
$keypress == $Gtk2::Gdk::Keysyms {Return })
{
&ExecTarget();
exit ZERO;
# Shouldn't get here
&PanicDialog ("#$REVISION-0031");
#ifdef NOTDEF # Not presently used
# return TRUE; # Consume the event
#endif
}
return FALSE; # Pass the event on to GTK2
}
#---------------------------------------------------------------------
# selection-window setup routine
#---------------------------------------------------------------------
# Future change: Document this routine.
sub RunSelectionWindow
{
my (%args) = @_; # Argument list
my $str; # Scratch
#---------------------------------------------------------------------
# Extract arguments.
my $ref_list = $args { -ref_list };
my $text = $args { -text };
my $title_list = $args { -title_list };
my $title_main = $args { -title_main };
&PanicDialog ("#$REVISION-0032")
unless defined ($ref_list ) || !defined ($text) ||
!defined ($title_list) || !defined ($title_main);
my $slump_checkbox = TRUE;
if (defined ($str = $args {-slump_checkbox}) &&
($str =~ m@^(0|zero|n|no|false)\z@i))
{
$slump_checkbox = FALSE;
}
#---------------------------------------------------------------------
# Close old window (if necessary).
if (defined $MainWindow)
{
Gtk2->main_quit;
$MainWindow->destroy;
undef $MainWindow;
}
#---------------------------------------------------------------------
# Create main window.
$MainWindow = Gtk2::Window->new;
$MainWindow->set_position ('GTK_WIN_POS_CENTER');
$MainWindow->set_title ($title_main);
$MainWindow->signal_connect
(delete_event => sub { Gtk2->main_quit; TRUE; });
$MainWindow->set_default_size ($MAIN_WIDTH, $MAIN_HEIGHT);
my $white = Gtk2::Gdk::Color->new (0xFFFF,0xFFFF,0xFFFF);
$MainWindow->modify_bg ('normal', $white);
$MainWindow->signal_connect
('key_release_event' => \&SpecialKeyHandler);
#---------------------------------------------------------------------
# Create some regions.
my $vbox = Gtk2::VBox->new (FALSE, 6);
$MainWindow->add ($vbox);
my $frame2 = Gtk2::Frame->new();
$vbox->pack_start ($frame2, TRUE, TRUE, ZERO);
$frame2->set_border_width (3);
#---------------------------------------------------------------------
# Create a Gtk2 "SimpleList" for the level-name list.
my $font_desc = Pango::FontDescription->from_string
('Liberation Sans Bold 14') ;
$SimpleList = Gtk2::SimpleList->new ($title_list => 'text');
$SimpleList->modify_font ($font_desc);
for (@$ref_list)
{
$str = $_;
$WadMap {$_} = $WadMap {$str} if s@^=\d+@=@;
$WadMap {$_} = $WadMap {$str}
if s@^= default level\z@(default level)@;
}
# This part is admittedly complicated
@{$SimpleList->{data}} = map { $_ = [ $_ ]; } @$ref_list;
$SimpleList->signal_connect (row_activated => \&ExecTarget);
$SimpleList->select (ZERO);
#---------------------------------------------------------------------
# Put the "SimpleList" in a Gtk2 "ScrolledWindow".
my $ListWindow = Gtk2::ScrolledWindow->new (undef, undef);
$ListWindow -> set_policy ('automatic', 'automatic');
$ListWindow -> add ($SimpleList);
if ($FlagDirectRendering)
{
$text .= << 'END';
You seem to have a modern graphics card, so high-resolution mode
is recommended. You can also use a low-resolution mode. The
second mode is fuzzier, but it'll work on most systems that
don't support the first mode.
END
}
else
{
$text .= << 'END';
This distro doesn't support accelerated graphics for your video
card, so 640x480 mode is recommended.
END
}
#---------------------------------------------------------------------
# Create a Gtk2 "TextView" for the message text.
my $textview = &LACGTK2_CreateTextView
(
-text => $text ,
-top_space => ONE
);
#---------------------------------------------------------------------
# Create option checkboxes.
$CB_AltMusic = new Gtk2::CheckButton
-> new_with_label ('Alt Music' );
($CB_AltMusic ->get_children) [0] -> modify_font ($font_desc);
$CB_HighRes = new Gtk2::CheckButton
-> new_with_label ('HighRes' );
($CB_HighRes ->get_children) [0] -> modify_font ($font_desc);
# The underscore here is intentional. It reduces an issue that occurs
# when the Spiders checkbox appears or disappears.
$CB_BeauDoom = new Gtk2::CheckButton
-> new_with_label ('Beautiful' );
($CB_BeauDoom ->get_children) [0] -> modify_font ($font_desc);
$CB_Leggo = new Gtk2::CheckButton
-> new_with_label ('Leggo_' );
($CB_Leggo ->get_children) [0] -> modify_font ($font_desc);
$CB_Save_Slump = new Gtk2::CheckButton
-> new_with_label ('Save Slump' );
($CB_Save_Slump ->get_children) [0] -> modify_font ($font_desc);
$CB_SciFi = new Gtk2::CheckButton
-> new_with_label ('SciFi' );
($CB_SciFi ->get_children) [0] -> modify_font ($font_desc);
$CB_Spiders = new Gtk2::CheckButton
-> new_with_label ('Spiders' );
($CB_Spiders ->get_children) [0] -> modify_font ($font_desc);
#---------------------------------------------------------------------
# Set default checkbox states.
$CFG_Leggo = FALSE if $CFG_SciFi ;
$CFG_SciFi = FALSE if $CFG_Leggo ;
$CB_AltMusic -> set_active ($CFG_AltMusic );
$CB_BeauDoom -> set_active ($CFG_BeauDoom );
$CB_HighRes -> set_active ($CFG_HighRes );
$CB_Leggo -> set_active ($CFG_Leggo );
$CB_Save_Slump -> set_active ($CFG_Save_Slump );
$CB_SciFi -> set_active ($CFG_SciFi );
$CB_Spiders -> set_active ($CFG_Spiders );
#---------------------------------------------------------------------
# Add option radio buttons/checkboxes to a table.
my $OptTable = Gtk2::Table->new (6, 2, FALSE);
$OptTable -> attach_defaults ($CB_SciFi , 0, 2, 0, 1);
$OptTable -> attach_defaults ($CB_AltMusic , 0, 2, 1, 2);
$OptTable -> attach_defaults ($CB_Leggo , 2, 4, 0, 1);
$OptTable -> attach_defaults ($CB_Spiders , 2, 4, 1, 2);
$OptTable -> attach_defaults ($CB_BeauDoom , 4, 6, 0, 1);
#ifdef NOTDEF
# $OptTable -> attach_defaults ($CB_HighRes , 2, 3, 0, 1);
# $OptTable -> attach_defaults ($CB_Save_Slump , 2, 3, 1, 2)
# if $slump_checkbox;
#endif
#---------------------------------------------------------------------
# Assemble all the pieces.
my $FrameText = Gtk2::Frame->new ('Instructions');
$FrameText -> set_border_width (3);
$FrameText -> add ($textview);
my $FrameOptions = Gtk2::Frame->new ('Options');
$FrameOptions -> set_border_width (3);
$FrameOptions -> add ($OptTable);
my $RightSide = Gtk2::VBox->new (FALSE, 6);
$RightSide -> pack_start ($FrameText , TRUE , 1, 0);
$RightSide -> pack_start ($FrameOptions , FALSE, 0, 4);
my $MainTable = Gtk2::Table->new (1, 4, TRUE);
$MainTable -> attach_defaults ($ListWindow , 0, 1, 0, 1);
$MainTable -> attach_defaults ($RightSide , 1, 4, 0, 1);
$frame2->add ($MainTable);
#---------------------------------------------------------------------
# Add OK/Quit buttons.
&LACGTK2_AddButtons
(
-vbox => $vbox ,
-action_ok => '&ExecTarget' ,
-action_quit => 'quit'
);
#---------------------------------------------------------------------
# Make everything visible.
$MainWindow->show_all;
#---------------------------------------------------------------------
# Handle character-mode side effects.
# If S.F. characters are selected (at startup time or afterwards),
# this code makes the "Spiders" checkbox visible.
# If S.F. characters are deselected (at startup time or afterwards),
# this code makes the "Spiders" checkbox invisible.
#---------------------------------------------------------------------
if ($CFG_SciFi)
{
$CB_Spiders -> show_all;
}
else
{
$CB_Spiders -> hide_all;
}
#---------------------------------------------------------------------
$CB_BeauDoom -> signal_connect ( clicked => sub
{
if ($CB_BeauDoom->get_active)
{ $CFG_BeauDoom = TRUE ; }
else
{ $CFG_BeauDoom = FALSE ; }
} );
#---------------------------------------------------------------------
$CB_Leggo -> signal_connect ( clicked => sub
{
if ($CB_Leggo->get_active)
{
$CB_SciFi -> set_active (FALSE);
$CB_Spiders -> hide_all;
$CFG_Leggo = TRUE ;
$CFG_SciFi = FALSE ;
}
else
{ $CFG_Leggo = FALSE; }
} );
#---------------------------------------------------------------------
$CB_SciFi -> signal_connect ( clicked => sub
{
if ($CB_SciFi->get_active)
{
$CB_Leggo -> set_active (FALSE);
$CB_Spiders -> show_all;
$CFG_Leggo = FALSE ;
$CFG_SciFi = TRUE ;
}
else
{
$CFG_SciFi = FALSE ;
$CB_Spiders -> hide_all;
}
} );
#---------------------------------------------------------------------
# Wrap it up.
Gtk2->main; # Start Gtk2 main loop
undef;
}
#---------------------------------------------------------------------
# Slump-selection screen
#---------------------------------------------------------------------
# "ReplayOldSlump" displays a screen that allows the user to select
# an old Slump level and play it.
sub ReplayOldSlump
{
my $data; # Data buffer
my @list = (); # List of Slump level-generation keys
my $str; # Scratch
#---------------------------------------------------------------------
# Initial setup.
&Load_CFG_PRFREEBOOM(); # Load "prfreeboom.cfg" settings
&CheckDirectRendering(); # Check status of direct rendering
&LocateSlumpHistory(); # Locate Slump history file
#---------------------------------------------------------------------
# Build list of old "Slump" levels.
open (IFD, "<$SLUMPFILE") ||
&PanicDialog ("#$REVISION-0033");
undef $/;
binmode IFD;
$data = ;
$data = "" unless defined $data;
close IFD;
$data =~ s@#[^\012]*@@g;
$data =~ s@^\s+@@s;
$data =~ s@\s+\z@@s;
$data =~ s@\s+@ @gs;
@list = sort reverse_by_number split (/\s+/, $data);
for (@list) { s@^(\d+)\b@Slump $1@; }
if ((scalar @list) > $MAX_SLUMP_LEVELS)
{
splice (@list, $MAX_SLUMP_LEVELS);
}
#---------------------------------------------------------------------
# Define message text (with tags).
# Note: The message text can use certain HTML-like tags, but HTML per
# se isn't supported. For more information, see the LACSUB code.
my $text = << 'END'; # 'END' must be single-quoted here
Use the box on the left to select a Slump level.
Left-click on a level name and press Enter
or click OK. Or you can just double-click.
To quit at this point, press Escape or
alt-Q, or click Quit.
Default controls: (after the
game starts)
1 to 5: Select weapon.
L-CTRL - Fire selected weapon.
Arrow keys: Move or turn.
Space: Jump. R-Shift: Open a door or activate a switch (or a lift).
Tab: Toggle Map mode. Escape: Quit.
Background:
Presently, you can replay the __META_MAX_SLUMP_LEVELS__ most recent
Slump levels. There's no provision for naming Slump levels or saving
them permanently, but these features may be added in the future.
END
$text =~ s@\b(Slump)\b@@g;
$text =~ s@__META_MAX_SLUMP_LEVELS__@100@g;
#---------------------------------------------------------------------
# Create/run selection window.
my $title_list = 'Old Slump Levels';
my $title_main = 'Replay old Slump level';
&RunSelectionWindow
(
-ref_list => \@list ,
-text => $text ,
-title_list => $title_list ,
-title_main => $title_main ,
-slump_checkbox => FALSE
);
undef;
}
#---------------------------------------------------------------------
# normal level-selection screen
#---------------------------------------------------------------------
sub NormalScreen
{
my $dirent; # Directory entry
my $str; # Scratch
#---------------------------------------------------------------------
# Initial setup.
&CheckDirectRendering(); # Check status of direct rendering
&LocateSlumpHistory(); # Locate Slump history file
#---------------------------------------------------------------------
# Build list of levels.
my $DEFAULT_PATH;
opendir (DIR, $DIR_LEVELS) ||
&PanicDialog ("#$REVISION-0034");
while (defined ($dirent = readdir (DIR)))
{
next unless $dirent =~ m@^([a-z0-9_\-]+)\.wad\z@i;
my $basename = $1;
my $path = "$DIR_LEVELS/$dirent";
next unless -f $path;
$str = $path;
$str =~ s@\.wad\z@.note@i;
my $note = "";
if (open (IFD, "<$str"))
{
$note = ;
close (IFD);
$note =~ s@^\s+@@s;
$note =~ s@\s+\z@@s;
$note =~ s@\s+@ @g;;
$note =~ s@^({.20}).+@$1...@;
}
$str = $basename;
$str =~ s@^tc_@=9 TC: @i;
$str =~ s@_+@ @g;
# Note: The following block makes adjustments to specific WAD-file
# names. The WAD files in question may (or may not) be present. How-
# ever, if they're not present, this code shouldn't cause any prob-
# lems.
$str =~ s@^(The)(pits|tower|zoo)@$1 $2@i;
$str =~ s@^contain\z@Containment@i;
$str =~ s@^castle5\z@Castle-5@i;
$str =~ s@^castlem\z@Castle-M@i;
$str =~ s@(^| )([a-z])@$1 . uc ($2)@geis;
$str .= " - $note" if length $note;
$WadMap {$str} = $path;
$str = $dirent;
$str =~ s@\.wad\z@@i;
$DEFAULT_PATH = $path if $str =~ m@$DEFAULT_PATTERN@i;
}
closedir DIR;
$WadMap {'=0 default level'} = $DEFAULT_PATH
if defined $DEFAULT_PATH;
#ifdef NOTDEF
# $WadMap {'=1 Play FreeDoom' } = '__META_FREEDM__' ;
#endif
$WadMap {'=2 Create a Slump level' } = '__META_SLUMP__' ;
$WadMap {'=3 Create a Slige level' } = '__META_SLIGE__' ;
# This feature is disabled for now because there are two glitches:
# (a) Selecting this mode launches the first saved level without the
# opportunity to select a level. (b) There should be a way to delete
# old levels.
if (FALSE && (-f $SLUMPFILE) && (!-z $SLUMPFILE))
{
$WadMap {'=4 replay old Slump levels'} = '__META_OLDSLUMP__';
}
#---------------------------------------------------------------------
# Define message text (with tags).
# Notes:
#
# a. The message text can use certain HTML-like tags, but HTML per se
# isn't supported. For more information, see the LACSUB code.
#
# b.